The compiler reports E08030 on my discount lookup. What is wrong and how do I fix it?
← Debugging and Troubleshooting · Ref: Q993
E08030 means you called an accessor on an Optional, Result or Iterator (get(), ok(), error(), next()) without first proving it holds a value. It is only raised for those types: an ordinary value such as a Float that might be unset can be used directly, and the result is simply unset too.
IN THIS CODE:
lookupDiscount returns an Optional of Float - empty for an unknown product. The failing code calls .get() straight away:
lookupDiscount()
-> productCode as String
<- rtn as Optional of Float: Optional() of Float
if productCode == "PREMIUM"
rtn: Optional(0.20)
basePrice <- 100.0 discount <- lookupDiscount("PREMIUM") finalPrice <- basePrice - (basePrice * discount.get()) // ERROR E08030: not checked before access stdout.println($finalPrice)
THE FIX:
Use a declaration guard, which declares the variable AND checks that it is set:
if discount <- lookupDiscount(productCode) finalPrice <- basePrice - (basePrice * discount.get())
The body only runs when the Optional holds a discount, so the get() inside it is safe. 'if discount?' after a separate declaration works the same way.
ALTERNATIVELY:
Ask the Optional for a default, so there is nothing to check:
rate <- lookupDiscount(productCode).getOrDefault(0.0) finalPrice <- basePrice - (basePrice * rate)
This uses 0.0 (no discount) when the Optional is empty.
Example
defines module qa.debugging.diagnoseerror defines function lookupDiscount() as pure -> productCode as String <- rtn as Optional of Float: Optional() of Float premiumCode <- "PREMIUM" standardCode <- "STANDARD" if productCode == premiumCode rtn: Optional(0.20) else if productCode == standardCode rtn: Optional(0.10) defines program DiagnoseErrorDemo() stdout <- Stdout() basePrice <- 100.0 //Correct: the guard checks the Optional, so get() inside the body is safe if discount <- lookupDiscount("PREMIUM") finalPrice <- basePrice - (basePrice * discount.get()) stdout.println(`Discounted price: ${finalPrice}`) //Correct: getOrDefault needs no check - an unknown product gets 0.0 standardDiscount <- lookupDiscount("UNKNOWN").getOrDefault(0.0) regularPrice <- basePrice - (basePrice * standardDiscount) stdout.println(`Regular price: ${regularPrice}`)
Common mistakes
E08030 — Calling get() on an Optional that has not been checked is rejected. Use a guard 'if v <- expr()' (or 'if v?') before get(), or getOrDefault(). See ek9 -h E08030.
Incorrect:
discount <- lookupDiscount("PREMIUM") finalPrice <- basePrice - (basePrice * discount.get()) stdout.println(`Discounted price: ${finalPrice}`)
Correct:
if discount <- lookupDiscount("PREMIUM") finalPrice <- basePrice - (basePrice * discount.get()) stdout.println(`Discounted price: ${finalPrice}`)
E01073 — 'null' does not exist in EK9. Use a guard 'if v <- expr()' to check the Optional, or the ? suffix: 'if discount?'. See ek9 -h E01073.
Incorrect:
discount <- lookupDiscount("PREMIUM") if discount != null finalPrice <- basePrice - (basePrice * discount.get()) stdout.println(`Discounted price: ${finalPrice}`)
Correct:
if discount <- lookupDiscount("PREMIUM") finalPrice <- basePrice - (basePrice * discount.get()) stdout.println(`Discounted price: ${finalPrice}`)
Other ways to ask this
- Diagnose this E08030 error in my EK9 code
- Why is the compiler saying unsafe access on this line?
- Help me understand and fix E08030 in this code
Coming from another language?
E08030 in EK9 is like calling Optional.get() in Java without isPresent(), or unwrap() in Rust - except EK9 rejects it at compile time instead of throwing at runtime. There is no escape hatch.
Keywords: Optional, E08030, access, fix, guard, unsafe, getOrDefault, diagnose