Agent Wranglers

Errors and nulls Required

Throw exceptions instead of returning error codes

Signal failure with an exception or a typed result. Never return a magic value such as -1, false or an error string that callers must remember to check.

How to do it

Throw when a function cannot do its job. Catch the error where you can handle it, often at the edge of the request. In languages built on result values, such as Go or Rust, return the error type and let the compiler force the check.

Example

// Bad: callers must remember that -1 means "not found"
public function stockFor(string $sku): int
{
    return $this->rows[$sku] ?? -1;
}

// Good: failure cannot be mistaken for a number
public function stockFor(Sku $sku): int
{
    return $this->rows[$sku->value] ?? throw new UnknownProduct($sku);
}
# Bad
def stock_for(sku: str) -> int:
    return rows.get(sku, -1)

# Good
def stock_for(sku: Sku) -> int:
    if sku.value not in rows:
        raise UnknownProduct(sku)
    return rows[sku.value]

How to check

A strict type checker requires a declared return type on every function. Examples are PHPStan at level max, TypeScript strict and mypy --strict. A grep fails return types that join a value with false, such as int|false. Reviewers fail any sentinel value, such as -1 for not found.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers architecture playbook: https://agentwranglers.se/playbook/architecture/errors-and-nulls/exceptions-not-error-codes.