{"record":{"id":"632caa9a1b792f7b","repo":"gitbutlerapp/gitbutler","slug":"no-commits-are-available-for-integration","errorCode":null,"errorMessage":"No commits are available for integration.","messagePattern":"No commits are available for integration\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/src/lib/upstream/branchIntegrationEditor.ts","lineNumber":34,"sourceCode":"\t| {\n\t\t\tid: string;\n\t\t\tkind: \"pick\" | \"merge\";\n\t\t\tcommitId: string;\n\t  }\n\t| {\n\t\t\tid: string;\n\t\t\tkind: \"squash\";\n\t\t\tcommitIds: string[];\n\t\t\tmessage: string;\n\t  };\n\nfunction createStepId() {\n\treturn crypto.randomUUID();\n}\n\nfunction firstCommitId(commitOptions: CommitPickerOption[]): string {\n\tconst first = commitOptions[0];\n\tif (!first) throw new Error(\"No commits are available for integration.\");\n\treturn first.id;\n}\n\nfunction secondCommitId(commitOptions: CommitPickerOption[], selectedCommitId: string): string {\n\tconst second = commitOptions.find((option) => option.id !== selectedCommitId);\n\treturn second?.id ?? selectedCommitId;\n}\n\nfunction isIntegrated(commit: Pick<IntegrationDivergenceCommit, \"targetRelation\">): boolean {\n\treturn commit.targetRelation.kind !== \"notIntegrated\";\n}\n\nexport function buildCommitPickerOptions(\n\tinitialIntegration: InitialBranchIntegration,\n): CommitPickerOption[] {\n\treturn [\n\t\t...initialIntegration.divergence.localOnly\n\t\t\t.filter((commit) => !isIntegrated(commit))","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/apps/desktop/src/lib/upstream/branchIntegrationEditor.ts#L16-L52","documentation":"Thrown by the module-level helper firstCommitId when given an empty CommitPickerOption array. Integration step drafts require at least one commit to pick as the integration target, so an empty list is unrecoverable at this point. Callers build integration drafts (default drafts, primary commit id, kind changes) from the commit options of a branch.","triggerScenarios":"Calling firstCommitId (indirectly via createDefaultIntegrationStepDraft, primaryCommitId, or changeIntegrationStepDraftKind) with commitOptions === [] — i.e. the branch has no commits available for integration.","commonSituations":"Opening the branch integration editor on a branch with zero commits, an unborn/orphan branch, or commit data that failed to load and defaulted to an empty array.","solutions":["Check that the branch has at least one commit before opening the integration editor or building a draft.","Handle empty commit lists in the editor UI by showing a disabled/empty state instead of constructing a draft.","Investigate why commitOptions is empty if the branch should have commits (fetch/refresh failure)."],"exampleFix":"// before\nconst draft = createDefaultIntegrationStepDraft(commitOptions);\n// after\nif (commitOptions.length === 0) {\n  showEmptyIntegrationState();\n  return;\n}\nconst draft = createDefaultIntegrationStepDraft(commitOptions);","handlingStrategy":"validation","validationCode":"if (commitOptions.length === 0) {\n  renderEmptyIntegrationState();\n  return;\n}\nconst draft = createDefaultIntegrationStepDraft(commitOptions);","typeGuard":"function hasCommits(opts: CommitPickerOption[]): opts is [CommitPickerOption, ...CommitPickerOption[]] {\n  return opts.length > 0;\n}","tryCatchPattern":"try {\n  const draft = createDefaultIntegrationStepDraft(commitOptions);\n} catch {\n  showEmptyIntegrationState();\n}","preventionTips":["Guard the integration editor against branches with zero commits","Treat empty commit lists as a distinct UI state, not an error path","Verify commit data actually loaded before constructing drafts"],"tags":["integration","empty-list","branch"],"backgroundTag":"empty-result-set","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}