nocobase/nocobase · error · Error

head node not found in workflow (#${this.execution.workflowI

Error message

head node not found in workflow (#${this.execution.workflowId})

What it means

When rerun is called without an explicit nodeId, getRerunNode derives the rerun start point from the workflow's head node (the node with no upstream). If no such node exists — the workflow graph is cyclic or has multiple disconnected entry nodes — it throws because rerun cannot determine where to start.

Source

Thrown at packages/plugins/@nocobase/plugin-workflow/src/server/Processor.ts:387

      return await this.run(node, input, { rerun: true });
    } finally {
      this.rerunContext = null;
      this.leaveRunningState();
    }
  }

  private getRerunNode(nodeId?: string | number) {
    if (nodeId != null) {
      const node = this.nodesMap.get(nodeId) || this.nodes.find((item) => String(item.id) === String(nodeId));
      if (!node) {
        throw new Error(`node (#${nodeId}) not found in workflow (#${this.execution.workflowId})`);
      }
      return node;
    }

    const head = this.nodes.find((item) => !item.upstream);
    if (!head) {
      throw new Error(`head node not found in workflow (#${this.execution.workflowId})`);
    }
    return head;
  }

  private getRerunInput(node: FlowNodeModel) {
    if (!node.upstream) {
      return { result: this.execution.context };
    }

    const upstreamJob = this.jobsMapByNodeKey[node.upstream.key];
    if (!upstreamJob) {
      throw new Error(`upstream job of node (#${node.id}) not found in execution (#${this.execution.id})`);
    }

    return upstreamJob;
  }

  private async exec(

View on GitHub (pinned to fa42722fef)

Solutions

  1. Inspect flow_nodes for the workflow: exactly one node should have upstreamId null; fix broken upstreamId values.
  2. Call rerun with an explicit valid nodeId instead of relying on head detection.
  3. Rebuild/duplicate the workflow in the UI if its graph is corrupted.
  4. Verify nodes loaded (execution.workflow.nodes non-empty) before rerunning.

Example fix

// before
await processor.rerun({});
// after
const head = execution.workflow.nodes.find((n) => !n.upstream);
if (!head) {
  console.error(`workflow ${execution.workflowId} has no head node; fix node graph`);
} else {
  await processor.rerun({ nodeId: head.id });
}
Defensive patterns

Strategy: validation

Validate before calling

const nodes = await workflow.getNodes();
const head = nodes.find((n) => !n.upstream);
if (!head) {
  throw new Error(`workflow ${workflow.id} graph is corrupted: no head node (check flow_nodes.upstreamId for cycles)`);
}

Type guard

function hasSingleHead(nodes: FlowNodeModel[]): boolean {
  return nodes.filter((n) => !n.upstream).length === 1;
}

Try / catch

try {
  await processor.rerun({});
} catch (e) {
  if (/head node not found/.test(e.message)) {
    logger.error(`workflow ${execution.workflowId} has no head node; repair graph or pass explicit nodeId`);
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: processor.rerun({}) on a workflow whose node list contains no node with item.upstream falsy — corrupted node graph, all nodes have upstream links (cycle), or nodes failed to load so the list is incomplete/empty.

Common situations: Manually edited workflow node relationships creating a cycle; import/copy of a workflow losing the head node; data corruption in flow_nodes.upstreamId; rerunning an execution whose workflow nodes were never loaded (nodes array empty in this pass).

Related errors


AI-assisted analysis of nocobase/nocobase@fa42722fef (2026-09-01). Data as JSON: /api/errors/586c33efa441d097. Report an issue: GitHub.