{"record":{"id":"54fc966621c7b018","repo":"ruvnet/ruflo","slug":"task-not-found-taskid","errorCode":null,"errorMessage":"Task not found: ${taskId}","messagePattern":"Task not found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/mcp/src/task-manager.ts","lineNumber":255,"sourceCode":"  getTasksByState(state: TaskState): TaskResult[] {\n    return Array.from(this.tasks.values())\n      .filter((task) => task.state === state)\n      .map((task) => ({\n        taskId: task.id,\n        state: task.state,\n        progress: task.progress,\n        result: task.result,\n        error: task.error,\n      }));\n  }\n\n  /**\n   * Wait for task completion\n   */\n  async waitForTask(taskId: string, timeout?: number): Promise<TaskResult> {\n    const task = this.tasks.get(taskId);\n    if (!task) {\n      throw new Error(`Task not found: ${taskId}`);\n    }\n\n    const effectiveTimeout = timeout ?? this.options.taskTimeout;\n\n    return new Promise((resolve, reject) => {\n      const checkState = () => {\n        const result = this.getTask(taskId);\n        if (!result) {\n          reject(new Error(`Task not found: ${taskId}`));\n          return true;\n        }\n        if (result.state === 'completed' || result.state === 'failed' || result.state === 'cancelled') {\n          resolve(result);\n          return true;\n        }\n        return false;\n      };\n","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/mcp/src/task-manager.ts#L237-L273","documentation":"TaskManager keeps tasks in an in-memory Map keyed by the id returned from createTask(); waitForTask() looks the id up both before starting its polling Promise and again on every poll tick, and throws 'Task not found: <taskId>' when the id is absent. Tasks are never persisted, and a cleanup timer (cleanupOldTasks, default every 60s) deletes finished tasks once their TTL passes. So the error means: this manager never knew the task, or already forgot it.","triggerScenarios":"Calling waitForTask() with an id from a different TaskManager instance or a previous process run; waiting after cleanupOldTasks() has removed the finished task (wait longer than taskTtl); passing a typo'd or truncated taskId; calling waitForTask() with a hardcoded id in tests against a fresh manager.","commonSituations":"Producer/consumer split across processes where the consumer only receives the id; integration tests that construct a new TaskManager per case but reuse fixed ids; long waits on short-lived tasks so TTL cleanup wins; MCP server restart between submit and wait.","solutions":["Call taskManager.getTask(taskId) first and treat undefined as 'unknown or expired task' instead of waiting","Only wait on ids returned by createTask() on the same TaskManager instance in the same process","Raise taskTtl (and cleanupInterval) in createTaskManager options so waits can outlive cleanup","Subscribe to 'task:completed'/'task:failed' events or await work inside the task executor instead of a long waitForTask"],"exampleFix":"// before\nconst result = await taskManager.waitForTask(taskId, 60_000);\n\n// after\nif (!taskManager.getTask(taskId)) {\n  throw new Error(`Unknown or expired task: ${taskId}`);\n}\nconst result = await taskManager.waitForTask(taskId, 60_000);","handlingStrategy":"validation","validationCode":"const snapshot = taskManager.getTask(taskId);\nif (!snapshot) {\n  throw new Error(`Task ${taskId} unknown or TTL-expired - not waiting`);\n}\nconst result = await taskManager.waitForTask(taskId, timeout);","typeGuard":null,"tryCatchPattern":"try {\n  await taskManager.waitForTask(id, timeout);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Task not found')) {\n    // permanent condition (wrong id or cleaned up) - fail fast, never retry\n  } else {\n    throw e;\n  }\n}","preventionTips":["Keep createTask() and waitForTask() on the same TaskManager instance in the same process","Persist results via the executor or the 'task:completed' event instead of waiting past the TTL","Set taskTtl/cleanupInterval larger than your worst-case wait","Treat 'Task not found' as permanent - do not retry it"],"tags":["task-management","async","in-memory-state","validation"],"backgroundTag":"entity-not-found","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}