# Structured Generation Errors ## Purpose Promptkit should give downstream applications actionable, machine-readable details when the built-in OpenAI-compatible client receives a non-success HTTP response. Today the client reports only the status code and discards the provider response body. This makes ordinary configuration failures—such as an unsupported strict JSON Schema keyword—unnecessarily difficult to diagnose. ## Target End State Failures from the built-in transport are available through a public typed error that works with `errors.As` while continuing to match `ErrLLMGenerate` through `errors.Is`. The error should expose: - the HTTP status code; - a normalized provider error code or type when supplied; and - a bounded provider message extracted from a recognized OpenAI-compatible JSON error envelope. The ordinary `Error()` string should remain safe and concise: it should include the status and provider code or type, but not automatically include the provider message. Consumers that deliberately want the provider's diagnostic text can retrieve it from the typed error and apply their own disclosure and logging policy. This contract should be available for both ordinary and prepared execution. Errors returned by injected model clients must continue to preserve their own identity and should not be converted into fabricated HTTP details. ## Safety And Compatibility Boundaries - Never expose the raw response body, response headers, endpoint, credentials, request messages, schema document, or generated content through this API. - Read only a small fixed maximum response body, reject malformed or unrecognized envelopes, normalize invalid UTF-8 and control characters, and cap every retained diagnostic field independently. - Treat the extracted provider message as untrusted and potentially sensitive: its GoDoc must tell consumers not to log or display it without applying their own policy. - Preserve the existing generic behavior when a response is empty, non-JSON, oversized, or does not match a recognized error envelope. - Do not assign retryability from an HTTP status. Promptkit supplies facts; downstream applications retain retry and presentation policy. ## Recommended API Direction Prefer one immutable public `GenerationError` value, constructed internally and carrying accessors for HTTP status, provider code or type, and provider message. This keeps the exact representation evolvable while giving consumers an idiomatic `errors.As` contract. Public Go declarations and GoDoc should own the final exact names and semantics. The internal OpenAI-compatible client should parse only the conventional top-level `error` envelope and pass normalized details through the use-case and public error-mapping layers. The integration documentation should continue to own wire behavior; the public declarations should own the consumer contract. ## Acceptance Criteria - A downstream consumer can distinguish a provider HTTP 400 from other generation failures and obtain a bounded provider explanation when present. - The typed error still satisfies `errors.Is(err, ErrLLMGenerate)`. - Existing cancellation, capacity, validation, and injected-client error identities remain unchanged. - Tests cover recognized string and numeric provider codes, absent and malformed envelopes, oversized bodies and fields, control characters, and error-chain behavior without making live provider requests. - Current-state GoDoc and the OpenAI-compatible integration and internal-client documents are updated only when the implementation lands.