{"record":{"id":"fc9e64d707e64cc7","repo":"gitbutlerapp/gitbutler","slug":"textfromtoolresult-result","errorCode":null,"errorMessage":"textFromToolResult(result)","messagePattern":"textFromToolResult\\(result\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/but-mcp-app/src/ReviewApp.tsx","lineNumber":401,"sourceCode":"\t\t);\n\t}\n\n\tconst connectedApp = app;\n\tconst currentView = view;\n\tconst canCallTools = connectedApp.getHostCapabilities()?.serverTools !== undefined;\n\n\tasync function markReady(review: ReviewCardData) {\n\t\tsetPendingReview(review.number);\n\t\tsetActionError(null);\n\t\ttry {\n\t\t\tconst result = await connectedApp.callServerTool({\n\t\t\t\tname: \"gitbutler_mark_review_ready\",\n\t\t\t\targuments: {\n\t\t\t\t\trepository: currentView.repository.path,\n\t\t\t\t\treviewNumber: review.number,\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (result.isError) throw new Error(textFromToolResult(result));\n\t\t\tconst updatedView = reviewViewFromToolResult(result);\n\t\t\tconst updatedReview = updatedView?.reviews[0];\n\t\t\tif (!updatedReview) throw new Error(\"The updated review was missing from the response.\");\n\t\t\tsetView((current) =>\n\t\t\t\tcurrent === null || updatedView === null ? current : mergeReviewViews(current, updatedView),\n\t\t\t);\n\t\t} catch (actionCause) {\n\t\t\tsetActionError(\n\t\t\t\tactionCause instanceof Error ? actionCause.message : \"Could not mark the review ready.\",\n\t\t\t);\n\t\t} finally {\n\t\t\tsetPendingReview(null);\n\t\t}\n\t}\n\n\tasync function openReview(review: ReviewCardData) {\n\t\tsetActionError(null);\n\t\ttry {","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/2497b8007aa4a1922dae9a805b32ffe5b5037785/packages/but-mcp-app/src/ReviewApp.tsx#L383-L419","documentation":"Not a fixed message: at ReviewApp.tsx:401 the app throws new Error(textFromToolResult(result)) when the gitbutler_mark_review_ready tool answers with isError true. The actual string is the first text content item in the tool result (or \"The review operation failed.\" when there is none), i.e. the server-side failure explanation, displayed via setActionError next to the review card.","triggerScenarios":"gitbutler_mark_review_ready with {repository, reviewNumber} fails server-side: review number not found, review not in a markable state (already ready, merged, or closed), forge authentication expired, or a network failure reaching the forge.","commonSituations":"Stale review list where the review was closed or merged elsewhere; expired GitHub/forge token; review mid state-transition; repository path no longer matching an open project.","solutions":["Read the surfaced text — it is the tool's own failure reason, not a client-side guess","Refresh the review list and retry with a valid review still in draft state","Re-authenticate the forge integration if the text mentions authorization","Verify the repository path matches an open GitButler project"],"exampleFix":"// before\nif (result.isError) throw new Error(textFromToolResult(result));\n\n// after — keep the review number in the message for easier triage\nif (result.isError) throw new Error(`Mark review #${review.number} ready failed: ${textFromToolResult(result)}`);","handlingStrategy":"validation","validationCode":"// run before invoking gitbutler_mark_review_ready\nif (!view?.repository.path) throw new Error(\"No repository selected.\");\nif (review.state !== \"draft\") {\n\tdisableMarkReady(review.number); // non-draft reviews cannot be marked ready — avoid the doomed call\n}","typeGuard":null,"tryCatchPattern":"try {\n\tconst result = await connectedApp.callServerTool({\n\t\tname: \"gitbutler_mark_review_ready\",\n\t\targuments: { repository: currentView.repository.path, reviewNumber: review.number },\n\t});\n\tif (result.isError) throw new Error(textFromToolResult(result)); // tool text is the real reason\n} catch (actionCause) {\n\tsetActionError(actionCause instanceof Error ? actionCause.message : \"Could not mark the review ready.\");\n}","preventionTips":["Disable the action for reviews not in a markable (draft) state","Refresh the review list before acting so review numbers are current","Check result.isError first and display its text verbatim — it is the server's own diagnosis","Re-check forge authentication when the text mentions authorization"],"tags":["mcp","reviews","tool-error"],"backgroundTag":"mcp-tool-error-result","analyzedSha":"2497b8007aa4a1922dae9a805b32ffe5b5037785","analyzedAt":"2026-08-17T00:30:25.648Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}