nocodb/nocodb · error · Error
Integration loader not available. This node must be executed
Error message
Integration loader not available. This node must be executed within a workflow context.
What it means
Thrown by AbstractWorkflowNode.getIntegration when this._integrationLoader is unset. The loader is injected by the workflow executor via setIntegrationLoader before node.run()/fetchOptions() execute, so a missing loader means the node instance was used outside the executor — e.g. constructed directly in a test or called from application code rather than dispatched through the workflow runtime.
Source
Thrown at packages/noco-integrations/core/src/workflow-node/types.ts:182
* async run(ctx: WorkflowNodeRunContext) {
* const auth = await this.getIntegration(this.config.authIntegrationId);
* const data = await auth.use(async (client) => {
* return client.api.getData();
* });
* }
*
* // Loading an AI integration with type
* async run(ctx: WorkflowNodeRunContext) {
* const ai = await this.getIntegration<AiIntegration>(this.config.aiIntegrationId);
* const result = await ai.generateText({ prompt: 'Hello' });
* }
* ```
*/
protected async getIntegration<T = any>(
integrationId: string
): Promise<T> {
if (!this._integrationLoader) {
throw new Error('Integration loader not available. This node must be executed within a workflow context.');
}
return this._integrationLoader<T>(integrationId);
}
public abstract definition(): Promise<WorkflowNodeDefinition>;
public async validate(_config: TConfig): Promise<WorkflowNodeValidationResult> {
return { valid: true };
}
public abstract run(ctx: WorkflowNodeRunContext): Promise<WorkflowNodeResult>;
public async fetchOptions(
_key: string,
_searchQuery?: string,
): Promise<unknown> {
return []
}View on GitHub (pinned to d3caaf4e89)
Solutions
- Run the node through the workflow executor (the standard path) so setIntegrationLoader is called automatically before run/fetchOptions.
- In tests, call node.setIntegrationLoader(async (id) => mockIntegrationFor(id)) before invoking run/fetchOptions.
- Avoid constructing workflow nodes with `new` in application code — obtain them from the workflow registry/executor.
- If you genuinely need a node outside the executor, inject a loader explicitly before any method that calls getIntegration.
Example fix
// before (test)
const node = new MyNode();
await node.run({}); // throws: Integration loader not available...
// after
const node = new MyNode();
node.setIntegrationLoader(async (id) => mockIntegrations[id]);
await node.run({}); Defensive patterns
Strategy: validation
Validate before calling
function nodeHasLoader(node: any): boolean {
return typeof node?._integrationLoader === 'function';
}
if (!nodeHasLoader(node)) {
throw new Error('Refusing to call run() on a node without an integration loader; run via the workflow executor.');
} Type guard
function isDispatchableNode<N extends { _integrationLoader?: unknown }>(
node: N,
): node is N & { _integrationLoader: (id: string) => Promise<unknown> } {
return typeof node._integrationLoader === 'function';
} Try / catch
try {
await node.run(ctx);
} catch (err) {
if (err instanceof Error && /Integration loader not available/.test(err.message)) {
// surface 'attach this node to a workflow first' to the user / test author
throw new Error('Node must be executed within a workflow context');
}
throw err;
} Prevention
- Always obtain nodes from the workflow executor, not via `new`.
- In tests, call node.setIntegrationLoader(...) before run/fetchOptions.
- Treat getIntegration as executor-only and document it on the node class.
When it happens
Trigger: Calling node.getIntegration('id') (transitively: node.run, node.fetchOptions, or any override that calls getIntegration) on a node instance that was constructed with `new MyNode()` directly rather than instantiated and dispatched by the workflow executor. Also when a node method is invoked before the executor has called setIntegrationLoader, or in unit tests that exercise run() without wiring the loader.
Common situations: Unit tests that `new MyNode()` and call .run() without injecting a loader; a node class whose fetchOptions is hit by the UI before the node is attached to a workflow; refactoring that moves getIntegration calls out of run() into a constructor/standalone helper that runs before the executor sets the loader.
Related errors
- Integration not configured properly
- Integrations table not found
- Refresh token not available for this integration
- Connection to internal hosts is not allowed
- Source is not ${clientType}
AI-assisted analysis of nocodb/nocodb@d3caaf4e89 (2026-08-12).
Data as JSON: /api/errors/58abe7d5ed95dda6.
Report an issue: GitHub.