earendil-works/pi · error · PiMessagesResponseError

${response.status} ${response.statusText}…

Error message

${response.status} ${response.statusText}: ${suffix}${codeSuffix}

What it means

Error constructed by createPiMessagesResponseError when the pi.dev messages streaming endpoint answers a non-2xx status: the thrown error's message combines HTTP status/statusText with the provider's error body suffix and a code suffix. It fires on every failed request attempt in stream(); transient statuses are expected to be handled by the retryProviderRequest wrapper surrounding the call, which is why the throw carries full response context.

Solutions

  1. The API returned an HTTP error; check the status code and response suffix for details.
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at packages/ai/src/api/pi-messages.ts:398 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of earendil-works/pi@4af9d21d3b (2026-08-24). Data as JSON: /api/errors/8e58d0d50f313ce7. Report an issue: GitHub.

Appendix: source

Thrown at packages/ai/src/api/pi-messages.ts:398

			}

			const response = await (options?.fetch ?? globalThis.fetch)(url, {
				method: "POST",
				headers: {
					authorization: `Bearer ${apiKey}`,
					accept: "text/event-stream",
					"content-type": "application/json",
					...providerHeadersToRecord(options?.headers),
				},
				body: JSON.stringify(payload),
				signal: options?.signal,
			});

			await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);

			if (!response.ok) {
				const body = await response.text();
				throw createPiMessagesResponseError(model, url, response, body);
			}
			if (!response.body) {
				throw new Error(`${model.provider} response has no body`);
			}

			for await (const piEvent of readPiMessagesEvents(response.body)) {
				const event = convertEvent(piEvent);
				eventStream.push(event);
				if (event.type === "done" || event.type === "error") {
					return;
				}
			}

			throw new Error(`${model.provider} stream ended without a terminal event`);
		} catch (error) {
			eventStream.push(createErrorEvent(model, error, options?.signal?.aborted ?? false));
		}
	})();

View on GitHub (pinned to 4af9d21d3b)