paperclipai/paperclip · error
Environment variable
Error message
Environment variable ${envName} is empty or not set. What it means
HTTP 404 with body {"error":"User secret definition not found"} from PATCH /api/companies/:companyId/user-secret-definitions/:definitionId (secrets.ts:658). svc.updateUserSecretDefinition(companyId, definitionId, ...) returned null: no updatable definition matched the (companyId, definitionId) pair - the definition was deleted, its status was already terminal (e.g. a prior update set status 'deleted'), it belongs to another company, or it never existed. Route requires secret-definition admin (assertSecretDefinitionAdmin) and the company must match the definition.
Solutions
- Re-list the company's user secret definitions and confirm the definitionId is still present and not already deleted.
- If you intended deletion, do not PATCH afterwards - deletion is terminal through this route; recreate the definition instead.
- Verify :companyId matches the company the definition actually lives in.
- On race with another admin, re-fetch, re-apply the surviving fields, and surface a conflict to the user instead of retrying.
Example fix
// before
await api.patch(`/api/companies/${companyId}/user-secret-definitions/${defId}`, { status: 'active' });
// after
const defs = await api.listUserSecretDefinitions(companyId);
if (!defs.some((d) => d.id === defId && d.status !== 'deleted')) {
throw new Error(`definition ${defId} missing, cross-company, or already deleted`);
}
await api.patch(`/api/companies/${companyId}/user-secret-definitions/${defId}`, { status: 'active' }); Defensive patterns
Strategy: validation
Validate before calling
async function patchDefinitionSafe(api: ApiClient, companyId: string, definitionId: string, patch: unknown) {
const defs = await api.fetch(`/api/companies/${companyId}/user-secret-definitions`);
const list = await defs.json();
const target = (Array.isArray(list) ? list : list.items ?? []).find(
(d: { id: string; status?: string }) => d.id === definitionId && d.status !== 'deleted',
);
if (!target) throw new Error(`definition ${definitionId} missing or already deleted`);
return api.fetch(`/api/companies/${companyId}/user-secret-definitions/${definitionId}`, {
method: 'PATCH',
body: JSON.stringify(patch),
});
} Type guard
function isApiErrorBody(body: unknown): body is { error: string } {
return typeof body === 'object' && body !== null &&
typeof (body as Record<string, unknown>).error === 'string';
}
const isDefinitionNotFound = (b: unknown): boolean =>
isApiErrorBody(b) && b.error === 'User secret definition not found'; Try / catch
try {
await api.patch(`/api/companies/${companyId}/user-secret-definitions/${defId}`, patch);
} catch (err) {
if (err instanceof ApiError && err.status === 404 && isDefinitionNotFound(err.body)) {
await reloadDefinitions(companyId); // deleted concurrently or wrong company
return;
}
throw err;
} Prevention
- Never PATCH a definition after setting its status to 'deleted' - recreate instead.
- Reload definition lists in admin UIs right before save.
- Keep definition IDs company-scoped in config; never copy between tenants.
- Require secret-definition admin rights in scripts and check them before bulk edits.
When it happens
Trigger: Patching a definition that was concurrently deleted by another admin; setting status to 'deleted' in one request and then patching it again; using a definitionId from a different company than :companyId; definition IDs stale after a reseed or after definitions were migrated.
Common situations: Admin UI forms kept open across a definition removal; automation that 'disables then edits' definitions in quick succession; copy/paste of definition IDs between staging and production tenants.
Related errors
- Challenge secret is required. Pass --token or --token-env.
- Cannot build API path with an empty path segment.
- Company ID is required. Pass --company-id, set…
- Could not locate local Paperclip skills directory. Expected…
- Failed to create API key
AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18).
Data as JSON: /api/errors/a2877d88bd0e6420.
Report an issue: GitHub.
Appendix: source
Thrown at cli/src/commands/client/auth.ts:200
handleCommandError(err);
}
}),
);
}
}
function parseJson(value: string): unknown {
return JSON.parse(value) as unknown;
}
function resolveChallengeToken(opts: AuthChallengeOptions): string {
const token = opts.token?.trim();
if (token) return token;
const envName = opts.tokenEnv?.trim();
if (envName) {
const envValue = process.env[envName]?.trim();
if (envValue) return envValue;
throw new Error(`Environment variable ${envName} is empty or not set.`);
}
throw new Error("Challenge secret is required. Pass --token or --token-env.");
}
View on GitHub (pinned to 120ae5428f)