Skip to main content

Failure semantics

Failure semantics are a first-class part of an interpreter’s contract. How an interpreter signals success, failure, or partial completion directly affects user trust, automation reliability, and the ability to reason about outcomes.

Interpreters must make failure states explicit, predictable, and understandable without requiring users to inspect logs or infer meaning from side effects.

Success vs failure

An interpreter must clearly distinguish between success, failure, and partial success.

  • Success indicates that the intended outcome was achieved within the bounds of the interpreter contract.
  • Failure indicates that the intended outcome wasn’t achieved and that corrective action may be required.
  • Partial success indicates that some (but not all) elements of the intended outcome were achieved.

Partial success isn’t an error condition by itself. It must be explicitly represented when applicable, along with structured details describing:

  • Which actions succeeded
  • Which actions failed or were skipped
  • The implications for downstream steps

Interpreters must avoid ambiguous outcomes. Users and automation should never be required to infer success or failure from exit codes, logs, or side effects alone.

Error messaging

Error messages are part of the user experience and must be designed accordingly.

Interpreters should distinguish between:

  • Human-readable, actionable errors, intended to help users understand what went wrong and how to correct it
  • Diagnostic details, intended for troubleshooting and support

Human-readable errors:

  • Use clear, plain language
  • Explain what failed and why
  • Indicate whether retrying is appropriate
  • Avoid exposing raw engine errors as the primary message

Diagnostic information:

  • May include engine output, stack traces, or low-level details
  • Should be captured in stdout or stderr
  • Must not be required to interpret the structured outcome

By separating actionable errors from diagnostic detail, interpreters support both usability and effective debugging without conflating the two.

Determinism and idempotency guidance

Interpreters should behave deterministically whenever possible.

A deterministic interpreter produces the same structured output when invoked with the same inputs under the same conditions. Determinism improves predictability, testability, and user confidence.

Idempotency is strongly preferred for interpreters that perform changes. An idempotent interpreter can be safely re-run without causing unintended side effects.

When determinism or idempotency can’t be guaranteed:

  • The limitation must be explicitly documented
  • Output must clearly indicate when non-deterministic behavior occurred
  • Users must be informed how to reason about retries and re-execution

Silent non-determinism undermines trust and makes automation fragile.

Retries, re-execution, and safety

Interpreters don’t control retries, but they must be designed to behave safely when re-executed.

Interpreter contracts should:

  • Clearly indicate whether retrying is safe
  • Distinguish transient failures from permanent ones where possible
  • Avoid side effects that make retries dangerous without warning

Where re-execution may cause additional changes or risk, the interpreter must make this explicit through its structured output and documentation.

Timeouts, cancellation, and incomplete execution

Interpreters may be interrupted due to timeouts, cancellation, or environmental failure.

Interpreter output must clearly communicate when execution was:

  • Completed
  • Partially completed
  • Aborted before meaningful work occurred

Users should never be left guessing whether changes were applied when execution is interrupted. Structured output must reflect the final known state as accurately as possible.

Where precise state can’t be determined, the interpreter must explicitly state that uncertainty exists.

Thank you for your feedback!

×