{"record":{"id":"5dcbf09887a72d1d","repo":"BloopAI/vibe-kanban","slug":"result-message-push-failed","errorCode":null,"errorMessage":"result.message || 'Push failed'","messagePattern":"result\\.message \\|\\| 'Push failed'","errorType":"exception","errorClass":"PushErrorWithData","httpStatus":null,"severity":"error","filePath":"packages/web-core/src/shared/hooks/usePush.ts","lineNumber":31,"sourceCode":"}\n\nexport function usePush(\n  workspaceId?: string,\n  onSuccess?: () => void,\n  onError?: (\n    err: unknown,\n    errorData?: PushError,\n    params?: PushWorkspaceRequest\n  ) => void\n) {\n  const queryClient = useQueryClient();\n\n  return useMutation<void, unknown, PushWorkspaceRequest>({\n    mutationFn: async (params: PushWorkspaceRequest) => {\n      if (!workspaceId) return;\n      const result = await workspacesApi.push(workspaceId, params);\n      if (!result.success) {\n        throw new PushErrorWithData(\n          result.message || 'Push failed',\n          result.error\n        );\n      }\n    },\n    onSuccess: () => {\n      // A push only affects remote status; invalidate the same branchStatus\n      queryClient.invalidateQueries({\n        queryKey: ['branchStatus', workspaceId],\n      });\n      onSuccess?.();\n    },\n    onError: (err, variables) => {\n      console.error('Failed to push:', err);\n      const errorData =\n        err instanceof PushErrorWithData ? err.errorData : undefined;\n      onError?.(err, errorData, variables);\n    },","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/packages/web-core/src/shared/hooks/usePush.ts#L13-L49","documentation":"The push mutation calls workspacesApi.push; when the response indicates success=false it throws PushErrorWithData with the server's message (result.message) or the fallback 'Push failed'. Like the force-push wrapper, it forwards the structured result.error so callers can branch on the specific failure reason.","triggerScenarios":"Invoking push on a workspace when the backend rejects the push: Git credential/token issues, a non-fast-forward remote (remote has commits you don't), merge conflicts blocking the push, workspace locked by a running process, or the git push subprocess failing on the server.","commonSituations":"Remote branch advanced since the last sync (needs pull/rebase first); expired provider token; pushing with no commits on the task branch; SSH key not loaded on the host running the backend; protected-branch rejection.","solutions":["Inspect the PushErrorWithData .error field / server message for the exact git failure and address it (pull/rebase if non-fast-forward)","Re-authenticate the Git provider or fix the credential used by the workspace","Ensure no attempt is currently running on the workspace (lock) and retry","Verify the remote branch exists and your branch has commits to push"],"exampleFix":"// before\nthrow new PushErrorWithData(\n  result.message || 'Push failed',\n  result.error\n);\n// after\nthrow new PushErrorWithData(\n  result.message || `Push failed for workspace ${workspaceId}`,\n  result.error\n);\n// caller:\ntry {\n  push(params);\n} catch (e) {\n  if (e instanceof PushErrorWithData && e.error?.type === 'non_fast_forward') {\n    promptPullAndRetry();\n  }\n}","handlingStrategy":"try-catch","validationCode":"// Before pushing: ensure there are commits and remote state is fresh\nconst behind = await gitApi.isBranchBehind?.(workspaceId);\nif (behind) return showToast('Remote is ahead — pull/rebase first');\nif (workspace.isAttemptRunning) return showToast('Workspace is busy');","typeGuard":"function isPushError(e: unknown): e is PushErrorWithData {\n  return e instanceof PushErrorWithData;\n}","tryCatchPattern":"useMutation({...}).mutateAsync(params).catch((e) => {\n  if (isPushError(e)) {\n    if (e.error?.type === 'non_fast_forward') promptPullAndRetry();\n    else showToast(e.message);\n  }\n});","preventionTips":["Pull/rebase before pushing when the remote may have moved","Keep Git provider credentials fresh","Don't push while an attempt is running","Distinguish PushErrorWithData from generic errors so the structured e.error can guide recovery"],"tags":["git","push","api-error","react-query"],"backgroundTag":"git-push-failed","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}