jlcodes99/cockpit-tools · error
API_KEY_REQUIRED
API_KEY_REQUIRED
Error message
API_KEY_REQUIRED
What it means
updateApiKeyOnCodexModelProvider sanitizes the supplied secret with sanitizeApiKey and throws API_KEY_REQUIRED when the normalized value is empty — i.e. the call would replace the key with nothing. This is an input-validation guard executed before the provider lookup, so an empty key never reaches the store.
Source
Thrown at src/services/codexModelProviderService.ts:815
if (!apiKey) throw new Error('API_KEY_NOT_FOUND');
const now = Date.now();
apiKey.name = sanitizeName(name);
apiKey.updatedAt = now;
provider.updatedAt = now;
await writeProviders(providers);
return { ...provider, apiKeys: provider.apiKeys.map((item) => ({ ...item })) };
}
/** Replace the secret for an existing provider API key without changing its id. */
export async function updateApiKeyOnCodexModelProvider(
providerId: string,
apiKeyId: string,
apiKey: string,
name?: string,
): Promise<CodexModelProvider> {
const normalizedApiKey = sanitizeApiKey(apiKey);
if (!normalizedApiKey) throw new Error("API_KEY_REQUIRED");
const providers = await ensureProvidersLoaded();
const provider = providers.find((item) => item.id === providerId);
if (!provider) throw new Error("PROVIDER_NOT_FOUND");
const existing = provider.apiKeys.find((item) => item.id === apiKeyId);
if (!existing) throw new Error("API_KEY_NOT_FOUND");
const duplicate = provider.apiKeys.some(
(item) => item.id !== apiKeyId && sanitizeApiKey(item.apiKey) === normalizedApiKey,
);
if (duplicate) throw new Error("API_KEY_EXISTS");
const now = Date.now();
existing.apiKey = normalizedApiKey;
if (name !== undefined) {
existing.name = sanitizeName(name);
}
existing.updatedAt = now;View on GitHub (pinned to 1ed8b77992)
Solutions
- Ensure a non-empty key is passed: check apiKey.trim().length > 0 before calling.
- Fix the source of the empty value (set the env var, correct the config path, re-copy the secret).
- If you meant to delete the key, use removeApiKeyFromCodexModelProvider instead of updating to an empty value.
- Catch 'API_KEY_REQUIRED' and show a 'key must not be empty' prompt in the UI.
Example fix
// before
await updateApiKeyOnCodexModelProvider(providerId, keyId, process.env.NEW_KEY ?? '');
// after
const key = process.env.NEW_KEY;
if (!key || !key.trim()) throw new Error('NEW_KEY must be set to rotate the API key');
await updateApiKeyOnCodexModelProvider(providerId, keyId, key.trim()); Defensive patterns
Strategy: validation
Validate before calling
const key = (apiKey ?? '').trim();
if (!key) throw new Error('API_KEY_REQUIRED: new key material must be non-empty'); Type guard
function isNonEmptySecret(value: unknown): value is string {
return typeof value === 'string' && value.trim().length > 0;
} Try / catch
try {
await updateApiKeyOnCodexModelProvider(providerId, apiKeyId, apiKey, name);
} catch (e) {
if ((e as Error).message === 'API_KEY_REQUIRED') {
showFieldError('apiKey', 'Enter the new API key value');
} else throw e;
} Prevention
- Check the secret is non-empty after trimming before any key update.
- Fail fast at startup when env vars supplying key material are unset.
- Use removeApiKeyFromCodexModelProvider for deletions instead of updating to empty.
- Validate clipboard pastes in forms (non-empty, expected prefix) before submitting.
When it happens
Trigger: Calling updateApiKeyOnCodexModelProvider(providerId, apiKeyId, apiKey, name?) where sanitizeApiKey(apiKey) returns '' — apiKey is '', whitespace, undefined-as-string, or a value stripped entirely by sanitization (e.g. only characters the sanitizer removes).
Common situations: Rotating a key but pasting an empty clipboard; an env var (e.g. PROVIDER_API_KEY) unset so the code passes an empty string; form field cleared then saved; reading the key from a config that returns null coerced to ''.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- SUB2API_API_KEY_MISSING
- Official auth.json requires OPENAI_API_KEY for API Key accou
- invalidJsonMessage
- messages.noItems
- messages.providerMismatch
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/a41227771de70f57.
Report an issue: GitHub.