{"record":{"id":"97a0398d508ee826","repo":"gitbutlerapp/gitbutler","slug":"no-stacks-found-in-the-workspace","errorCode":null,"errorMessage":"No stacks found in the workspace","messagePattern":"No stacks found in the workspace","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-action/src/simple.rs","lineNumber":70,"sourceCode":"        context_lines,\n    )\n    .map_err(|err| serde_error::Error::new(&*err))?;\n    if assignments.is_empty() {\n        return Ok(Outcome {\n            updated_branches: vec![],\n        });\n    }\n\n    // Get the current stacks in the workspace, creating one if none exists.\n    let stacks = stacks_creating_if_none(repo, ws, meta, perm)?;\n\n    // Put the assignments into buckets by stack ID.\n    let mut stack_assignments: HashMap<StackId, Vec<DiffSpec>> =\n        stacks.iter().map(|s| (s.id, vec![])).collect();\n    let default_stack_id = stacks\n        .first()\n        .map(|s| s.id)\n        .ok_or_else(|| anyhow::anyhow!(\"No stacks found in the workspace\"))?;\n    for assignment in assignments {\n        if let Some(stack_id) = assignment.stack_id {\n            stack_assignments\n                .entry(stack_id)\n                .or_default()\n                .push(assignment.into());\n        } else if exclusive_stack.is_none() {\n            // If there is an exclusive stack. We don't want to do anything with\n            // the unassigned changes.\n            stack_assignments\n                .entry(default_stack_id)\n                .or_default()\n                .push(assignment.into());\n        }\n    }\n    // Go over the stack_assignments and flatten the diff specs for each stack.\n    for (_, specs) in stack_assignments.iter_mut() {\n        *specs = but_workspace::flatten_diff_specs(specs.clone());","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/2497b8007aa4a1922dae9a805b32ffe5b5037785/crates/but-action/src/simple.rs#L52-L88","documentation":"In the simplified handle-changes commit flow, stacks_creating_if_none is supposed to return the applied stacks, creating one when the workspace has none. If it still yields an empty list, the subsequent stacks.first() fails with this error — a defensive invariant violation meaning the workspace reported no usable stacks even after the create-if-none step.","triggerScenarios":"but-action simple::handle_changes with non-empty hunk assignments but an empty stacks list — stacks that exist but are all filtered out (unapplied / without refs) and the create-if-none step not producing an applied stack.","commonSituations":"Inconsistent or half-migrated workspace metadata; stacks left in detached/archived state after failed operations; races where another process mutated workspace refs between listing and commit.","solutions":["Create or apply a stack in the GitButler app (so at least one applied branch exists), then retry handle-changes.","Check workspace health first: `but status` should list at least one applied branch.","If it persists, workspace state is likely inconsistent — re-onboard the project or restore from the oplog.","Report as a bug: this branch is defensive and should be unreachable when stack creation works."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before invoking handle-changes:\nlet stacks = workspace::stacks(ctx, None)?;\nlet has_applied = stacks.iter().any(|s| !s.heads.is_empty());\nanyhow::ensure!(has_applied, \"apply or create a stack before running handle-changes\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep at least one applied stack in every managed workspace.","Verify `but status` lists applied branches before triggering agent commit flows.","Treat this error as a workspace-state bug to report, not a user mistake."],"tags":["workspace","stacks","invariant","agent-action","internal-state"],"backgroundTag":"no-applied-virtual-branch","analyzedSha":"2497b8007aa4a1922dae9a805b32ffe5b5037785","analyzedAt":"2026-08-17T00:30:25.648Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}