{"record":{"id":"1c0b90da9996529c","repo":"eyaltoledano/claude-task-master","slug":"cannot-finalize-workflow-working-tree-has-uncommi","errorCode":null,"errorMessage":"Cannot finalize workflow: working tree has uncommitted changes.\nStaged: ${statusSummary.staged}, Modified: ${statusSummary.modified}, Deleted: ${statusSummary.deleted}, Untracked: ${statusSummary.untracked}\nPlease commit all changes before finalizing the workflow.","messagePattern":"Cannot finalize workflow: working tree has uncommitted changes\\.\nStaged: (.+?), Modified: (.+?), Deleted: (.+?), Untracked: (.+?)\nPlease commit all changes before finalizing the workflow\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/workflow/services/workflow.service.ts","lineNumber":518,"sourceCode":"\t */\n\tasync finalizeWorkflow(): Promise<WorkflowStatus> {\n\t\tif (!this.orchestrator) {\n\t\t\tthrow new Error('No active workflow. Start or resume a workflow first.');\n\t\t}\n\n\t\tconst phase = this.orchestrator.getCurrentPhase();\n\t\tif (phase !== 'FINALIZE') {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot finalize workflow in ${phase} phase. Complete all subtasks first.`\n\t\t\t);\n\t\t}\n\n\t\t// Check working tree is clean\n\t\tconst gitAdapter = new GitAdapter(this.projectRoot);\n\t\tconst statusSummary = await gitAdapter.getStatusSummary();\n\n\t\tif (!statusSummary.isClean) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot finalize workflow: working tree has uncommitted changes.\\n` +\n\t\t\t\t\t`Staged: ${statusSummary.staged}, Modified: ${statusSummary.modified}, ` +\n\t\t\t\t\t`Deleted: ${statusSummary.deleted}, Untracked: ${statusSummary.untracked}\\n` +\n\t\t\t\t\t`Please commit all changes before finalizing the workflow.`\n\t\t\t);\n\t\t}\n\n\t\t// Capture task ID before transitioning\n\t\tconst context = this.orchestrator.getContext();\n\t\tconst taskId = context.taskId;\n\n\t\t// Transition to COMPLETE\n\t\tawait this.orchestrator.transition({ type: 'FINALIZE_COMPLETE' });\n\n\t\t// Get final status before cleanup\n\t\tconst finalStatus = this.getStatus();\n\n\t\t// Mark main task as done (use workflow's tag from context)","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/workflow/services/workflow.service.ts#L500-L536","documentation":"Thrown by WorkflowService.finalizeWorkflow() after checking the git working tree via GitAdapter.getStatusSummary(). Finalization requires a clean tree so the workflow's final commit is unambiguous; any staged, modified, deleted, or untracked files abort the finalization with a detailed breakdown.","triggerScenarios":"Calling finalizeWorkflow() while the project root has uncommitted git changes: staged files, modified tracked files, deleted files, or untracked files — i.e. statusSummary.isClean is false.","commonSituations":"A subtask step wrote files without committing them, the developer made manual edits mid-workflow, generated artifacts/logs are left untracked, or a .gitignore gap leaves tooling output visible to git.","solutions":["Commit or stash all pending changes: run `git status` to review, then `git add -A && git commit` (or `git stash`).","Add intentional generated files (logs, build output) to .gitignore so the tree reports clean.","Re-run finalizeWorkflow() after the tree is clean.","If the changes belong to the workflow, complete the intended commit step of the workflow instead of finalizing directly."],"exampleFix":"// before\nawait workflowService.finalizeWorkflow(); // throws: uncommitted changes\n// after\nimport { execSync } from 'node:child_process';\nif (execSync('git status --porcelain').toString().trim() === '') {\n  await workflowService.finalizeWorkflow();\n} else {\n  execSync('git add -A && git commit -m \"WIP: before workflow finalize\"');\n  await workflowService.finalizeWorkflow();\n}","handlingStrategy":"validation","validationCode":"import { execSync } from 'node:child_process';\nconst dirty = execSync('git status --porcelain', { cwd: projectRoot }).toString().trim();\nif (dirty) throw new Error('Commit or stash changes before finalizing workflow:\\n' + dirty);","typeGuard":null,"tryCatchPattern":"try {\n  await workflowService.finalizeWorkflow();\n} catch (e) {\n  if (e.message.startsWith('Cannot finalize workflow: working tree has uncommitted changes')) {\n    // prompt user to commit/stash, then retry\n  } else throw e;\n}","preventionTips":["Run git status before finalize; commit or stash everything.","Keep .gitignore current so generated files never dirty the tree.","Automate a pre-finalize commit step in the workflow."],"tags":["git","workflow","uncommitted-changes"],"backgroundTag":"dirty-working-tree","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}