n8n-io/n8n · error · TransferCredentialError
400
400
Error message
You can't transfer a credential into the project that's already owning it.
What it means
Thrown by EnterpriseCredentialsService.transferOne when sourceProject.id === destinationProjectId. Transferring a credential to the project that already owns it is a no-op and is explicitly rejected. The check runs after both projects are resolved and access is verified, so the IDs are valid — just identical.
Source
Thrown at packages/cli/src/credentials/credentials.service.ee.ts:226
);
// 3. get source project
const sourceProject = ownerSharing.project;
// 4. get destination project
const destinationProject = await this.projectService.getProjectWithScope(
user,
destinationProjectId,
['credential:create'],
);
NotFoundError.isDefinedAndNotNull(
destinationProject,
`Could not find project with the id "${destinationProjectId}". Make sure you have the permission to create credentials in it.`,
);
// 5. checks
if (sourceProject.id === destinationProject.id) {
throw new TransferCredentialError(
"You can't transfer a credential into the project that's already owning it.",
);
}
// Transferring an end-user credential into a project is equivalent to creating
// one there, so it must clear the same createEndUser gate.
if (credential.isResolvable) {
await this.credentialsService.ensureCanManageEndUserCredential(user, destinationProject.id);
}
// 6. validate that the destination project has access to all external secret providers
if (
this.licenseState.isExternalSecretsLicensed() &&
this.externalSecretsConfig.externalSecretsForProjects
) {
const decryptedData = await this.credentialsService.decrypt(credential, true);
await validateAccessToReferencedSecretProviders(
destinationProject.id,View on GitHub (pinned to 5ac6606e81)
Solutions
- Pass a destination project ID different from the current owning project.
- Fetch the current owner project first and skip the transfer if it equals the destination.
- Fix the form/selector so it cannot target the current owner.
Example fix
// before
await transferCredential(id, currentOwnerProjectId);
// after
if (destinationId !== currentOwnerProjectId) {
await transferCredential(id, destinationId);
} Defensive patterns
Strategy: validation
Validate before calling
if (destinationProjectId === currentOwnerProjectId) {
throw new Error('Destination equals current owner — nothing to transfer.');
}
await transferOne(user, id, destinationProjectId); Prevention
- Filter the current owner out of the destination project picker.
- Skip the transfer call when source === destination.
- Default the destination to a value other than the current owner.
When it happens
Trigger: POST transfer-ownership with a destinationProjectId equal to the credential's current owning project.
Common situations: UI defaulting the destination dropdown to the current owner. Caller re-issuing a transfer after a partial success. Mis-routed automation passing the source project as destination.
Related errors
- 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
- File does not seem to contain credentials. Make sure the cre
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/15a9c4fc3b3bb7dc.
Report an issue: GitHub.