Common Errors
Understanding and fixing common Qosm errors.
Type errors
Unbound identifier
Error: Unbound identifier 'foo'
Cause: You referenced a name that doesn't exist in scope.
Fixes:
- Check for typos in the name
- If it's a module function, use qualified name:
Module.function - If it's a capability, make sure it's enabled in the Capabilities panel
- If it's defined later in the file, move it above the usage (Qosm bindings must be defined before use)
Type mismatch
Error: Expected String but got Int
Cause: A value has a different type than expected.
Common causes:
- Using
+instead of++for string concatenation - Forgetting
to_stringwhen building strings:`Count: {{ to_string n }}` - Passing arguments in the wrong order (Qosm functions are curried)
Effect not declared
Error: Undeclared effect 'Http.Get'
Cause: Your code uses a capability whose effect isn't in scope.
Fix: Enable the relevant capability in the workspace Capabilities panel. The effect and extern declarations are generated automatically.
Missing semicolon
Error: Parse error at line N
Cause: Often a missing ; at the end of a top-level binding.
Fix: Every top-level let, type, effect, and extern must end with ;:
let x = 1; // semicolon required
let y = x + 1; // even the last one
Runtime errors
QosmError variants
All capability calls return Result<T, QosmError>. The error constructors are:
| Constructor | When it occurs |
|-------------|----------------|
| ModelError{message: _} | LLM call failed (network, rate limit, invalid response) |
| ParseError{message: _} | JSON parsing failed (invalid format or schema mismatch) |
| PermissionError{message: _} | Capability access denied (domain restriction, missing credential) |
| FunctionError{message: _} | General function execution error |
Access the message with .message e:
match result with (
| Err{value: e} -> "Error: " ++ .message e
| Ok{value: v} -> to_string v)
Match failure
Error: Match failure
Cause: A match expression didn't find a matching branch.
Fix: Add a wildcard branch or handle all cases:
match value with (
| Some{value: x} -> x
| None -> 0) // handle the None case
Common mistakes
| Mistake | Fix |
|---------|-----|
| person.name | .name person (prefix field access) |
| "hello" + " world" | "hello" ++ " world" (use ++ for strings) |
| if x then a else b | match x with (\| true -> a \| false -> b) |
| arr.map(f) | map f arr (curried, not method syntax) |
| [x, ...rest] in expression | append [x] rest (spread is pattern-only) |
| greet @{text: String} "hi" | my_model @{text: String} \...`(@Type goes on the extern) | |let x = 1inside match arm |let x = 1 in ...(usein` form inside expressions) |