DEV Community

Cover image for n8n 'No testing function found for this credential' Fix
Mahdi BEN RHOUMA
Mahdi BEN RHOUMA

Posted on Originally published at iloveblogs.blog

n8n 'No testing function found for this credential' Fix

What actually changed

You built a custom n8n node with its own credential type. The node works in a workflow. You open the credential in the n8n UI, click Test, and instead of a green checkmark you get:

No testing function found for this credential.
Enter fullscreen mode Exit fullscreen mode

You double-check the node — credentialTest is defined in methods, testedBy is set on the credential declaration, everything compiles. n8n just refuses to see it. This is one of the most-reported custom-node issues in n8n's history — the original report is Stack Overflow q/75109822 and the underlying bug is tracked in n8n-io/n8n#8188, with users still reproducing it on 1.58+ and 1.94 well after the original fix landed.

The fix

The root cause is not a missing function. It is in LoadNodesAndCredentials.ts: n8n generates nodesToTestWith in dist/known/credentials.json but only reads supportedNodes when linking a credential to its test function. For custom and community nodes the two keys never match, so the linkage is dropped and the UI shows the "no testing function" message.

The fix that survives across n8n versions is to stop relying on credentialTest on the node and instead define the test directly on the credential class as an ICredentialTestRequest.

Before — the linkage that breaks

// credentials/MyApi.credentials.ts
import { ICredentialType, INodeProperties } from 'n8n-workflow';

export class MyApi implements ICredentialType {
  name = 'myApi';
  displayName = 'My API';
  // ❌ testedBy points at the node's credentialTest, which the loader
  //    never resolves for custom/community nodes.
  testedBy = 'MyApiNode';
  properties: INodeProperties[] = [
    {
      displayName: 'API Key',
      name: 'apiKey',
      type: 'string',
      typeOptions: { password: true },
      default: '',
    },
  ];
}

// nodes/MyApi.node.ts
export class MyApiNode implements INodeType {
  methods: INodeTypeMethods = {
    credentialTest: async (credentials) => {
      // n8n never calls this for a custom node.
      const res = await fetch('https://api.example.com/me', {
        headers: { Authorization: `Bearer ${credentials.apiKey}` },
      });
      return res.ok
        ? { status: 'OK', message: 'OK' }
        : { status: 'Error', message: `HTTP ${res.status}` };
    },
  };
}
Enter fullscreen mode Exit fullscreen mode

After — define test on the credential class

// credentials/MyApi.credentials.ts
import {
  ICredentialType,
  ICredentialTestRequest,
  INodeProperties,
} from 'n8n-workflow';

export class MyApi implements ICredentialType {
  name = 'myApi';
  displayName = 'My API';
  properties: INodeProperties[] = [
    {
      displayName: 'API Key',
      name: 'apiKey',
      type: 'string',
      typeOptions: { password: true },
      default: '',
    },
  ];

  // ✅ Self-contained test. No linkage through the node required.
  test: ICredentialTestRequest = {
    request: {
      baseURL: 'https://api.example.com',
      url: '/me',
      headers: {
        Authorization: '=Bearer {{$credentials.apiKey}}',
      },
    },
    rules: [
      {
        type: 'responseSuccessBody',
        properties: {
          key: 'data.id',
          value: (val: unknown) => typeof val === 'string',
          message: 'Credentials are valid.',
        },
      },
    ],
  };
}
Enter fullscreen mode Exit fullscreen mode

Remove testedBy from the credential and credentialTest from the node — they are dead code for custom nodes and only confuse future readers.

If you want to keep credentialTest on the node — package as a real module

The test: ICredentialTestRequest fix above works whether your node is symlinked into ~/.n8n/custom or installed as a real package — that is why it is the recommended path. If you instead want to keep the older credentialTest method on the node (for example to share test logic across several nodes), the linkage bug only bites when the node is loaded from ~/.n8n/custom. Package it as a real module and n8n loads it like a community node, where the loader resolves credentialTest:

cd your-node-folder && npm pack
npm install /path/to/your-node.tgz
Enter fullscreen mode Exit fullscreen mode

Restart n8n. The n8n-generate-metadata build step you see in n8n's own nodes-base package is part of n8n's internal build pipeline and is not a workaround for custom nodes — the community thread on this bug (community.n8n.io) confirms that running it does not fix ~/.n8n/custom loads.

Verifying the fix

  1. Restart n8n (the credential registry is loaded at startup).
  2. Open your credential in the UI → the Test button should run an actual request, not show the warning.
  3. Put in a fake API key → the rule must fail with your message, not a generic error.
  4. Put in a valid key → green checkmark.
  5. If you packaged as a real module, grep your built output: grep "myApi" node_modules/your-node/dist/known/credentials.json should list your credential with supportedNodes. If you symlinked into ~/.n8n/custom, skip this — the test property on the credential class is what makes the test button work there, not the metadata file.

The credential file reference in the n8n docs (credentials-files) documents the test property format; the community thread on the bug (community.n8n.io) is the most up-to-date record of which n8n versions still reproduce it.

Related Incidents


Originally published at https://www.iloveblogs.blog

Top comments (0)