can1357/oh-my-pi · error · ProviderHttpError
mnemopi remote LLM request unauthorized (401)
Error message
mnemopi remote LLM request unauthorized (401)
What it means
callRemoteLlm sends a request to the configured remote LLM endpoint and maps an HTTP 401 response to this ProviderHttpError (status 401, carrying the response headers). It means the configured credentials were rejected by the remote provider — the server explicitly said the request is unauthorized.
Source
Thrown at packages/mnemopi/src/core/local-llm.ts:366
const fetchImpl = options.fetch ?? fetch;
try {
// withAuth re-resolves the key on 401 (force-refresh, then sibling
// rotation) when the configured key is a resolver. An empty static key
// attempts without an Authorization header (local/proxy setups).
const response = await withAuth(llmApiKey(), async key => {
const headers: Record<string, string> = { "Content-Type": "application/json" };
if (key !== "") {
headers.Authorization = `Bearer ${key}`;
}
const res = await fetchWithRetry(`${baseUrl}/chat/completions`, {
method: "POST",
headers,
body,
signal: AbortSignal.timeout(60000),
fetch: fetchImpl,
});
if (res.status === 401) {
throw new ProviderHttpError("mnemopi remote LLM request unauthorized (401)", 401, { headers: res.headers });
}
return res;
});
if (!response.ok) {
return null;
}
const data = (await response.json()) as {
choices?: Array<{ message?: { content?: unknown } }>;
};
const content = data.choices?.[0]?.message?.content;
return typeof content === "string" ? content : null;
} catch {
return null;
}
}
export function localGgufAvailable(): false {
return false;View on GitHub (pinned to 9690622007)
Solutions
- Verify the API key/token configured for the remote LLM endpoint is current and re-set it if rotated
- Confirm the credential has access to the exact model/endpoint being called
- Check that the env var holding the key is actually present in the runtime environment (container/CI often drops it)
- Test the key against the endpoint with curl to isolate mnemopi config vs provider-side rejection
Example fix
// before
{ "remoteLlm": { "apiKey": "sk-stale-..." } }
// after
{ "remoteLlm": { "apiKey": "sk-current-..." } } // or set via env Defensive patterns
Strategy: try-catch
Validate before calling
const apiKey = process.env.MNEMOPI_REMOTE_LLM_API_KEY;
if (!apiKey || apiKey.length < 8) {
throw new Error("remote LLM API key missing/short; set MNEMOPI_REMOTE_LLM_API_KEY before calling");
} Type guard
function hasCredential(cfg: { apiKey?: unknown }): cfg is { apiKey: string } {
return typeof cfg.apiKey === "string" && cfg.apiKey.length > 0;
} Try / catch
try {
const res = await callRemoteLlm(req);
// ...
} catch (err) {
if (err instanceof ProviderHttpError && err.status === 401) {
logger.error("remote LLM rejected credentials; refresh the API key", { url: req.url });
return null; // or requeue after credential refresh
}
throw err;
} Prevention
- Rotate and re-set API keys on a schedule; never hardcode them
- Verify the key is present in the deployment environment (container/CI) before starting
- Validate the key with a cheap authenticated endpoint at startup
- Scope credentials to the exact endpoint/model being called
When it happens
Trigger: The Authorization header (or equivalent) built from the configured API key/token is missing, expired, revoked, or scoped to a different endpoint when callRemoteLlm performs its fetch with a 60s timeout; any remote LLM call where res.status === 401.
Common situations: Rotated or mistyped API key in mnemopi config; expired token after SSO/session rotation; pointing the remote endpoint at a provider that doesn't accept the configured key; environment variable not set in the deployment (CI, container).
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Azure OpenAI API key is required. Set AZURE_OPENAI_API_KEY e
- Cursor API key (access token) is required
- DeepSeek API key is empty after stripping Bearer prefix
- OpenCode Go usage endpoint returned ${response.status}${deta
- Umans usage endpoint returned ${response.status} ${response.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8c2775a0dc8685cf.
Report an issue: GitHub.