mastra-ai/mastra · error
Linear did not accept the issue update.
Error message
Linear did not accept the issue update.
What it means
LinearIntegration throws this when Linear's GraphQL `issueUpdate` mutation completes but reports `success: false`, meaning the API rejected the state change (target state id, permissions, or issue state) even though the HTTP request itself succeeded. The mutation returns a payload without throwing, so the integration explicitly converts a falsy `success` into a thrown error. It indicates the issue's status was NOT changed.
Source
Thrown at mastracode/factory/src/integrations/linear/integration.ts:719
const wantedType = input.state.stateType;
targetState = states.find(state => state.type === wantedType) ?? null;
} else {
const wanted = input.state.name.toLowerCase();
targetState = states.find(state => state.name.toLowerCase() === wanted) ?? null;
}
if (!targetState) return null;
if (targetState.name === issue.state) {
return linearIssueToIntakeIssue(issue);
}
const data = await linearGraphql<{ issueUpdate: { success: boolean } }>(
accessToken,
`mutation UpdateIssueState($id: String!, $stateId: String!) {
issueUpdate(id: $id, input: { stateId: $stateId }) { success }
}`,
{ id: issue.id, stateId: targetState.id },
);
if (!data.issueUpdate.success) {
throw new Error('Linear did not accept the issue update.');
}
const fresh = await this.fetchIssueDetail(accessToken, issue.id);
if (!fresh) return null;
return linearIssueToIntakeIssue(fresh);
}
async #listTeamWorkflowStates(
accessToken: string,
teamKey: string,
): Promise<Array<{ id: string; name: string; type: string }>> {
const data = await linearGraphql<{
team: { states: { nodes: Array<{ id: string; name: string; type: string }> } } | null;
}>(
accessToken,
`query TeamStates($key: String!) {
team(id: $key) { states(first: 100) { nodes { id name type } } }
}`,
{ key: teamKey },View on GitHub (pinned to 75dd419e61)
Solutions
- Re-fetch the issue's team workflow states via Linear's API and retry the update with a freshly resolved `stateId` for the target state name.
- Verify the OAuth token used has the required `write` scope (issues) in Linear developer settings.
- Check the issue still exists and is not archived/canceled (`issueQuery` before update).
- Log the raw GraphQL response for `issueUpdate.userErrors`/errors to get Linear's specific rejection reason.
- Retry after a short backoff if the failure followed a concurrent state change.
Example fix
// before
if (!data.issueUpdate.success) {
throw new Error('Linear did not accept the issue update.');
}
// after
if (!data.issueUpdate.success) {
const states = await this.fetchTeamWorkflowStates(accessToken, teamId);
const refreshed = states.find(s => s.id === targetState.id) ?? states.find(s => s.name === targetState.name);
if (!refreshed) throw new Error(`State "${targetState.name}" no longer exists in Linear team ${teamId}.`);
await this.updateIssueState(accessToken, issue, refreshed);
} Defensive patterns
Strategy: retry
Validate before calling
const states = await getTeamWorkflowStates(accessToken, issue.teamId);
const target = states.find(s => s.id === targetState.id && s.type === 'started');
if (!target) throw new Error(`State ${targetState.id} not found for team ${issue.teamId}; refresh state ids before updating.`); Type guard
function isSuccessfulUpdate(r: { issueUpdate?: { success?: boolean } | null }): r is { issueUpdate: { success: true } } {
return r?.issueUpdate?.success === true;
} Try / catch
try {
await integration.updateIssueState(issue, targetState);
} catch (e) {
if (e.message === 'Linear did not accept the issue update.') {
await sleep(1000);
const fresh = await integration.fetchIssue(issue.id);
if (fresh) await integration.updateIssueState(fresh, targetState); // retry with fresh issue/state
} else throw e;
} Prevention
- Always resolve the target state id from a fresh workflow-state query for the issue's team, never from cache.
- Check the OAuth token has issue write scope when connecting the integration.
- Re-fetch the issue right before updating to catch archived/deleted issues.
- Log Linear's raw GraphQL errors alongside this message for diagnosis.
- Debounce concurrent automations that move the same issue.
When it happens
Trigger: Calling any LinearIntegration method that moves an issue between states (e.g. marking an issue in-progress/done) where Linear's `issueUpdate` mutation responds with `success: false` — typically because `stateId` does not belong to the issue's team, the state was deleted/renamed, the OAuth token lacks `write` scope for issues, or the issue was deleted/archived between lookup and update.
Common situations: The workflow state name lookup resolved a stale or wrong-team state id; a Linear workspace admin changed the team's workflow states; the bot token's scope was reduced; the issue was canceled or migrated while a task was running; concurrent automation already moved the issue to a state that blocks this transition.
Related errors
- Linear did not accept the comment.
- Linear API error: ${body.errors[0]?.message ?? 'unknown erro
- Linear API returned no data.
- Linear authorization expired. Reconnect Linear to keep synci
- Linear ${label} returned no access token.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/b0d683c615a2e5db.
Report an issue: GitHub.