{"record":{"id":"5f59508f7a24f4ce","repo":"stablyai/orca","slug":"commit-message-is-required","errorCode":null,"errorMessage":"Commit message is required","messagePattern":"Commit message is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/filesystem.ts","lineNumber":1419,"sourceCode":"      const filePath = validateGitRelativeFilePath(worktreePath, args.filePath)\n      const gitOptions = getLocalGitOptionsForRegisteredWorktree(\n        store,\n        args.worktreePath,\n        worktreePath\n      )\n      return getDiff(worktreePath, filePath, args.staged, args.compareAgainstHead, gitOptions)\n    }\n  )\n\n  ipcMain.handle(\n    'git:commit',\n    async (\n      _event,\n      args: { worktreePath: string; message: string; connectionId?: string }\n    ): Promise<{ success: boolean; error?: string }> => {\n      // Why: validate at the IPC boundary so the renderer gets a clear error instead of an opaque execFile failure.\n      if (typeof args.message !== 'string' || args.message.trim().length === 0) {\n        throw new Error('Commit message is required')\n      }\n      if (args.connectionId) {\n        const provider = getSshGitProvider(args.connectionId)\n        if (!provider) {\n          throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)\n        }\n        return provider.commit(args.worktreePath, args.message)\n      }\n      const worktreePath = await resolveRegisteredWorktreePath(args.worktreePath, store)\n      const gitOptions = getLocalGitOptionsForRegisteredWorktree(\n        store,\n        args.worktreePath,\n        worktreePath\n      )\n      return commitChanges(worktreePath, args.message, gitOptions)\n    }\n  )\n","sourceCodeStart":1401,"sourceCodeEnd":1437,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/filesystem.ts#L1401-L1437","documentation":"Thrown by the 'git:commit' handler (src/main/ipc/filesystem.ts:1419) when args.message is not a string or is empty/whitespace-only. The check runs at the IPC boundary so the renderer gets a clear error instead of an opaque execFile/git failure downstream, and it applies to both the remote (SSH provider) and local commit paths.","triggerScenarios":"Invoking ipcRenderer.invoke('git:commit', { worktreePath, message }) where message is undefined, null, '', or a string of only whitespace. The guard fires before any SSH provider lookup or local commit attempt.","commonSituations":"Commit dialog allowing submit with an empty textarea; an AI commit-message generator returning an empty string; a trim/normalization step that reduced the message to whitespace; message field dropped during IPC serialization.","solutions":["Pass a non-empty, trimmed commit message.","Disable the commit action in the UI until message.trim().length > 0.","If the message comes from an AI generator, validate its output and re-prompt on empty."],"exampleFix":"// before: empty message allowed through\nawait invoke('git:commit', { worktreePath, message: '' })\n\n// after: guard before invoking\nconst msg = message.trim()\nif (!msg) throw new UserError('Commit message is required')\nawait invoke('git:commit', { worktreePath, message: msg })","handlingStrategy":"validation","validationCode":"function isValidCommitMessage(m: unknown): m is string {\n  return typeof m === 'string' && m.trim().length > 0\n}","typeGuard":"const hasCommitMessage = (a: unknown): a is { message: string } =>\n  typeof (a as { message?: unknown })?.message === 'string' &&\n  ((a as { message: string }).message.trim().length > 0)","tryCatchPattern":null,"preventionTips":["Disable the commit button until message.trim() is non-empty.","Validate AI-generated commit messages and re-prompt on empty.","Trim/normalize the message before invoking git:commit."],"tags":["validation","git","ipc","commit"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}