ESC

Type to search...

Error Reference

EVOID captures exceptions in Result.error and stops the pipeline. The adapter converts the error to an HTTP response.

Exceptions

ValueError — Intent Not Registered / Validation Failed

Raised when executing an Intent that hasn’t been registered, or when a processor returns {"validated": False}.

# Intent not found
result = await execute(Intent(name="nonexistent", level=Level.STANDARD))
# Result: success=False, error=ValueError("Intent 'nonexistent' not registered")

# Validation rejection
async def validate(ctx):
    return {"validated": False, "error": "name is required"}
# Pipeline stops. Result: success=False, error=ValueError("Validation failed in validate: name is required")

Fix: register the Intent, or check validation return value.

PermissionError — Rejected by Processor

Raised when a processor returns {"authorized": False} or {"validated": False}. The _check_rejection() function in the pipeline detects rejection signals.

async def authorize(ctx):
    if not user_has_role(ctx, "admin"):
        return {"authorized": False, "reason": "admin only"}
    return {"authorized": True}
# Pipeline stops. Result: success=False, error=PermissionError("Rejected by authorize: admin only")

Fix: check result.error and return 403.

TimeoutError — Processor Timeout

Raised when a processor exceeds the Intent’s timeout. Default timeouts: EPHEMERAL=5s, STANDARD=10s, CRITICAL=30s.

PAYMENT = Intent(name="pay", level=Level.CRITICAL, timeout=5.0)
# If handler takes >5s: Result.error = TimeoutError("Processor 'pay' timed out after 5.0s")

Fix: increase timeout or optimize the processor.

LookupError — Processor Not Found

Raised in strict mode when a processor name in the pipeline doesn’t match any registered processor.

from evoid.core.runtime import Config

config = Config(strict=True)
result = await execute(intent, config=config)
# If pipeline references "unknown_processor": LookupError

Fix: check processor names against evo list-processors.

User-Raised Exceptions

Any exception raised by a handler is caught by the pipeline and stored in Result.error. The pipeline stops. The adapter returns HTTP 500.

async def handler(ctx):
    raise ValueError("Item not found")
# Result: success=False, error=ValueError("Item not found")
# HTTP 500: {"detail": "Item not found"}

Result Object

FieldTypeDescription
successboolTrue if pipeline completed without exception
valueAnyReturn value from last processor
errorException | NoneException if pipeline failed
processorstuple[str, ...]Processors that ran
durationfloatTotal execution time

Handling Errors

Check result.success

result = await execute(intent)
if result.success:
    return result.value
else:
    return {"error": str(result.error)}

Catch specific errors

try:
    result = await execute(intent)
except TimeoutError:
    return {"error": "timeout"}
except PermissionError:
    return {"error": "forbidden", "status": 403}

Collect non-critical errors

async def handler(ctx):
    try:
        validate(ctx.metadata["body"])
    except ValidationError as e:
        ctx.errors.append(e)  # Pipeline continues
    return {"validated": True, "warnings": len(ctx.errors)}