can1357/oh-my-pi · error

unexpected-stop: online classification failed: ${response.er

Error message

unexpected-stop: online classification failed: ${response.errorMessage ?? "unknown error"}

What it means

The online classifier's completion call returned stopReason === 'error'; classifyOnline surfaces the provider's errorMessage wrapped in this prefix. It is thrown after retryTransientCompletion exhausted retries, so the underlying failure is persistent (auth, rate limit, network, or model rejection).

Source

Thrown at packages/coding-agent/src/session/unexpected-stop-classifier.ts:120

			completeSimple(
				model,
				{
					systemPrompt: [CLASSIFIER_SYSTEM_PROMPT],
					messages: [{ role: "user", content: text, timestamp: Date.now() }],
				},
				{
					apiKey: deps.registry.resolver(model, deps.sessionId),
					maxTokens,
					disableReasoning: true,
					metadata,
					signal: deps.signal,
				},
			),
		{ signal: deps.signal },
	);

	if (response.stopReason === "error") {
		throw new Error(`unexpected-stop: online classification failed: ${response.errorMessage ?? "unknown error"}`);
	}

	const outputText = response.content
		.filter((part): part is { type: "text"; text: string } => part.type === "text")
		.map(part => part.text)
		.join("\n");
	return parseUnexpectedStopClassification(outputText);
}

async function classifyLocal(
	text: string,
	modelKey: string,
	deps: ClassifyUnexpectedStopDeps,
): Promise<boolean | undefined> {
	if (!isTinyMemoryLocalModelKey(modelKey)) {
		throw new Error(`unexpected-stop: unsupported local classifier model: ${modelKey}`);
	}
	const builtPrompt = prompt.render(unexpectedStopClassifierPrompt, { message: text });

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the embedded response.errorMessage to identify the root cause (auth vs rate limit vs network).
  2. Fix the underlying credential or network issue and retry.
  3. Increase maxTokens if the error indicates the reasoning model exceeded the token budget.
  4. Verify the tiny/smol model is still served by the provider (deprecated ids return errors).
Defensive patterns

Strategy: retry

Try / catch

try {
  verdict = await classifyUnexpectedStop(text, deps);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("unexpected-stop: online classification failed:")) {
    logger.warn("stop classification failed", { detail: err.message });
    verdict = undefined; // or retry with backoff for transient causes
  } else throw err;
}

Prevention

When it happens

Trigger: The streaming completion request to the tiny/smol model fails with an error stop reason on every retry: 401/403 from bad key, 429 rate limits, network outage, or the model rejects the request shape (e.g. maxTokens too small for a reasoning model).

Common situations: Expired/invalid API key; provider outage; rate limiting from bursty classification calls; using a reasoning model with ONLINE_REASONING_SAFE_MAX_TOKENS too low causing truncation errors; proxy/firewall blocking the endpoint.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/a9768cd3cabf7829. Report an issue: GitHub.