Skip to content

Errors ​

Every error chamvi throws extends ChamviError, which extends ebec's BaseError. Each carries a code; the codes are exported as ErrorCode.

ClassErrorCodeCodeThrown when
InvalidAgentDefinitionErrorINVALID_AGENT_DEFINITIONinvalid_agent_definitionAn agent name, trigger id or cron expression is invalid; duplicate agent names; an unknown notifier; an empty resumeSecret; dispatch() for an unknown agent
InvalidResumeTokenErrorINVALID_RESUME_TOKENinvalid_resume_tokenA resume token is malformed, forged, expired or belongs to another wait point
InvalidRunStateErrorINVALID_RUN_STATEinvalid_run_stateA run is not in the status an operation needs: resuming a run that is not waiting, cancelling a settled run, a store guard (expectStatus, expectOwner) that does not match
RunNotFoundErrorRUN_NOT_FOUNDrun_not_foundresume(), cancel() or updateRun() for an unknown run
ArtifactNotFoundErrorARTIFACT_NOT_FOUNDartifact_not_foundAn execution cannot read an artifact its messages refer to (the run fails); @chamvi/http answers 404 with it for an unknown artifact
BudgetExceededErrorBUDGET_EXCEEDEDBudgetExceededA run hit maxSteps or maxTokens while the model still wanted tools
TimeoutErrorTIMEOUTTimeoutAn execution exceeded timeoutMs
FatalToolErrorFATAL_TOOLFatalToolError (or a custom code)A tool decides the run must fail
IncompleteResponseErrorINCOMPLETE_RESPONSEincomplete_responseThe model gave no complete answer and the run fails: its stream ended without a finish part, or (with structured output) the answer was cut off at the output token limit or the loop ended on a tool call nothing executed
ToolNotAllowedErrorTOOL_NOT_ALLOWEDtool_not_allowedA call to a tool the agent's toolPolicy refuses: recorded on the tool step for a model's call to it, and returned to the model for an approved call from an older history; a tool error, the run goes on
LeaseLostErrorLEASE_LOSTlease_lostReported to onError when an engine stops executing a run whose claim it lost; carries runId
SandboxErrorSANDBOXsandbox_errorA workspace or its provider failed: a create, start or checkout (with git's stderr), a missing or oversized file, an unknown, expired or disposed workspace, a Docker or Kubernetes API error, a reached per-run workspace cap; a tool error, the run goes on
ValidationErrorVALIDATIONvalidation_errorA state document fails its schema (carries issues); an invalid attachment at dispatch() or artifacts.put(); a final answer that does not parse as the agent's structured output (the run fails); a workspace path, repository or ref the sandbox rules refuse (a tool error)

Run errors ​

A failed run stores { code, message } in run.error. For budget, timeout and fatal tool failures the code is the error's code. Any other thrown value gets its own code if it has a string one, else Error.

ts
const run = await engine.getRun(runId);
if (run?.status === RunStatus.FAILED) {
    switch (run.error?.code) {
        case ErrorCode.BUDGET_EXCEEDED:
            return 'Raise maxSteps or maxTokens, or narrow the instructions.';
        case ErrorCode.TIMEOUT:
            return 'Raise timeoutMs or make the tools faster.';
        case ErrorCode.FATAL_TOOL:
            return `A tool stopped the run: ${run.error.message}`;
        default:
            return run.error?.message;
    }
}

Errors without a caller ​

Some errors happen where nobody awaits: a lost lease, a failed notification, a listener that throws, a failed recovery pass. They go to onError(error, run?), by default console.error. Pass your logger. A LeaseLostError there is informational: another replica carries the run on.

ts
const engine = new Engine({
    store,
    agents,
    resumeSecret,
    onError: (error, run) => {
        if (error instanceof LeaseLostError) {
            // another replica carries the run on; nothing to do
            return;
        }
        logger.error({ err: error, runId: run?.id }, 'chamvi');
    },
});