n8n-io/n8n · error · CredentialNotFoundError
0
0
Error message
Credential with ID "${credentialId}" was not found. What it means
Thrown by CredentialsService.testById() when no stored credential matches the given ID, OR when the credential exists but is not project-scoped (e.g. it is an instance/provider credential). The method is reserved for the dynamic-credential test flow; instance credentials must be tested through testWithCredentials. CredentialNotFoundError extends UserError, surfacing as a not-found (HTTP 404) response.
Source
Thrown at packages/cli/src/credentials/credentials.service.ts:1218
`This credential is assigned to credential use "${result.credentialUseIds.join(', ')}" and cannot be deleted`,
);
}
return;
}
await this.credentialsRepository.remove(credential);
}
async test(userId: User['id'], credentials: ICredentialsDecrypted) {
return await this.credentialsTester.testCredentials(userId, credentials.type, credentials);
}
async testById(userId: User['id'], credentialId: string) {
const storedCredential = await this.credentialsFinderService.findCredentialById(credentialId);
// Dynamic-credential flows only; admins test instance credentials via testWithCredentials
if (!storedCredential || storedCredential.usageScope !== 'project') {
throw new CredentialNotFoundError(credentialId);
}
const credentials = await this.prepareCredentialsForTest({ storedCredential });
return await this.test(userId, credentials);
}
async testWithCredentials(user: User, credentials: ICredentialsDecrypted) {
const storedCredential = await this.credentialsFinderService.findCredentialForUser(
credentials.id,
user,
['credential:read'],
{ includeInstanceCredentials: true },
);
if (!storedCredential) {
if (credentials.id === '' && hasGlobalScope(user, 'credential:manageInstance')) {
this.validateInstanceCredentialData(credentials.data ?? {});
return await this.test(user.id, credentials);View on GitHub (pinned to 5ac6606e81)
Solutions
- Confirm the credential ID exists via GET /credentials/{id} before testing.
- For instance/provider credentials, use the testWithCredentials flow (testWithCredentials endpoint) instead of testById.
- Refresh the credentials list in the UI so the test button targets a current ID.
- If the credential was deleted, recreate it or pick a valid one from the current list.
Example fix
// before
await credentialsService.testById(userId, maybeInstanceId); // throws
// after
const stored = await credentialsFinderService.findCredentialById(id);
if (!stored || stored.usageScope !== 'project') {
return credentialsService.testWithCredentials(user, { id, type, data });
}
await credentialsService.testById(userId, id); Defensive patterns
Strategy: validation
Validate before calling
const stored = await credentialsFinderService.findCredentialById(credentialId);
if (!stored || stored.usageScope !== 'project') {
// route to testWithCredentials instead
}
await credentialsService.testById(userId, credentialId); Type guard
function isProjectCredentialId(id: unknown): id is string {
return typeof id === 'string' && id.trim().length > 0;
} Try / catch
try {
await credentialsService.testById(userId, credentialId);
} catch (e) {
if (e instanceof CredentialNotFoundError) {
// refresh credential list, fall back to testWithCredentials for instance creds
}
throw e;
} Prevention
- Differentiate the UI test action by credential usageScope (project vs instance).
- Re-fetch the credential before testing to avoid stale IDs.
- Prefer the type-appropriate test endpoint over a generic one.
When it happens
Trigger: POST /credentials/{id}/test where {id} does not exist; calling testById on an instance-scoped (provider connection) credential, which the dynamic flow does not support; testing a credential that was deleted between page load and click.
Common situations: Stale credential ID in a deep link or bookmark; frontend test button routed to the wrong endpoint for instance credentials; deleted credential still listed in a cached UI; off-by-one copy/paste of an ID.
Related errors
- 400
- Azure AI Search endpoint is missing or invalid
- Expected Supabase credentials host to be a string
- Provider connection data cannot be empty
- Provider connection data must be a JSON object
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/77a8d291f70151b0.
Report an issue: GitHub.