Skip to content
TE826 · Type · error

Collection method on un-unwrapped `Result`/`Option`

A collection method (`each`, `filter`, `len`, …) was called on a `Result` or `Option` wrapper directly. Unwrap it first with `?>`, `?`, or `.unwrap()`.

Why this fires

A collection method (each, for_each, forEach, filter, find, any, all, len, take, skip, collect, to_array, contains) was called on a value that is statically known to be a Result or Option wrapper. Those methods are dispatched to Array/Iter/Map at runtime and are never valid on an unwrapped wrapper.

use std::Database

let db = Database.open("sqlite://:memory:")?

db.query("SELECT * FROM users").each(|u| print(u.name))
//                              ^^^^ error[TE826]: `.each` does not exist on `Result<Rows, DbError>`;
//                                   unwrap the Result first: `expr ?> .each(...)` (fallible pipe),
//                                   `let v = expr?` then `v.each(...)`, or `.unwrap()`

The problem is that db.query(...) returns Result<Rows, DbError>. If you call .each on it directly, the runtime's Array.* fallback iterates the internal variant payload — the closure receives the whole rows array as one argument, .name is nil, and the call returns nil, silently. No error is ever raised; the wrong output just disappears.

The same applies to Option:

fn find_user(id: int) -> Option<User> { ... }

find_user(42).each(|u| print(u.name))
//            ^^^^ error[TE826]: `.each` does not exist on `Option<User>`;
//                 unwrap the Option first with `.unwrap()`, `.unwrap_or(...)`,
//                 or match on Some/None before calling `.each(...)`

Fix it

1. Fallible pipe ?> (propagate Err/None)

Use the fallible pipe operator to unwrap the Ok/Some value and chain into it, propagating any error up to the caller:

db.query("SELECT * FROM users") ?> .each(|u| print(u.name))

The function must declare a matching return type (Result<_, E> / Option<_>).

2. Bind then use

Unwrap with the ? postfix operator (propagates Err/None) and call the method on the bound value:

let rows = db.query("SELECT * FROM users")?
rows.each(|u| print(u.name))

3. .unwrap() (panics on Err/None)

If you are certain the result is always Ok/Some and a panic on failure is acceptable:

db.query("SELECT * FROM users").unwrap().each(|u| print(u.name))

Notes

  • Methods that already dispatch correctly on Result/Optionmap, map_err, and_then, or_else, unwrap, unwrap_or, unwrap_err, is_ok, is_err — are not flagged by TE826.
  • The check is by type name, so a user-declared enum literally named Result or Option also trips this error. The prelude names are effectively reserved.
  • Even without static type information a runtime guard in the prelude dispatchers catches the same mistake at runtime and emits a friendly message instead of the cryptic attempt to call method &#39;each&#39; (a nil value).
  • See docs/06-operators.md for the full ?> / ? / !. operator set.

See also

See also

enespt-br