{"record":{"id":"fc0c9416f37845bf","repo":"wtfutil/wtf","slug":"error-updating-task-s","errorCode":null,"errorMessage":"error updating task: %s","messagePattern":"error updating task: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/asana/client.go","lineNumber":134,"sourceCode":"\n\terr := t.Fetch(client)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error fetching task: %s\", err)\n\t}\n\n\tupdateReq := &asana.UpdateTaskRequest{}\n\n\tif *t.Completed {\n\t\tf := false\n\t\tupdateReq.Completed = &f\n\t} else {\n\t\tt := true\n\t\tupdateReq.Completed = &t\n\t}\n\n\terr = t.Update(client, updateReq)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error updating task: %s\", err)\n\t}\n\n\treturn nil\n}\n\nfunc processFetchedTasks(client *asana.Client, fetchedTasks *[]*asana.Task, taskItems *[]*TaskItem, uidToName *map[string]string, mode, projectId, uid string) {\n\n\tfor _, task := range *fetchedTasks {\n\t\tswitch {\n\t\tcase strings.HasSuffix(mode, \"_all\"):\n\t\t\tif task.Assignee != nil {\n\t\t\t\t// Check if we have already looked up this user\n\t\t\t\tif assigneeName, ok := (*uidToName)[task.Assignee.ID]; ok {\n\t\t\t\t\ttask.Assignee.Name = assigneeName\n\t\t\t\t} else {\n\t\t\t\t\t// We haven't looked up this user before, perform the lookup now\n\t\t\t\t\tassigneeName, err := getOtherUserEmail(client, task.Assignee.ID)\n\t\t\t\t\tif err != nil {","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/modules/asana/client.go#L116-L152","documentation":"Returned by toggleTaskCompletionById when asana.Task.Update fails after the task's current state was successfully fetched. The library computes the inverted Completed flag and issues an update request; any API rejection of that write is wrapped with this message. The toggle did not take effect.","triggerScenarios":"Calling t.Update(client, updateReq) with the flipped Completed bool when the API rejects the write: token lacks write scope on the task (comment-only or read-only integration), task is locked/completed-and-locked by policy, invalid token, rate limit, or network failure.","commonSituations":"OAuth app or PAT with read-only scopes used for a write operation; task in a project with rules that forbid edits; Asana 429 rate limiting after many rapid toggles; token expired between fetch and update.","solutions":["Verify the token/PAT has write scopes (OAuth apps need write scope for tasks).","Confirm the task is not restricted by project rules or permissions in Asana.","Check the wrapped HTTP status: 403 => permissions, 401 => re-auth, 429 => back off and retry the toggle.","Retry the operation; it is idempotent (toggle recomputes from freshly fetched state)."],"exampleFix":"// before\nerr = t.Update(client, updateReq)\nif err != nil {\n    return fmt.Errorf(\"error updating task: %s\", err)\n}\n// after\nerr = t.Update(client, updateReq)\nif err != nil {\n    return fmt.Errorf(\"error updating task %s: %w\", taskId, err)\n}","handlingStrategy":"try-catch","validationCode":"// confirm write access before toggling\nu, err := client.CurrentUser()\nif err != nil {\n    return fmt.Errorf(\"token invalid: %w\", err)\n}\n// ensure token has write scopes; read-only PATs will fail on Update","typeGuard":null,"tryCatchPattern":"err := mod.Toggle(taskId)\nif err != nil {\n    if strings.Contains(err.Error(), \"error updating task\") {\n        log.Printf(\"update rejected for %s; check write scopes and project rules: %v\", taskId, err)\n        return err // surface to caller; state is unchanged\n    }\n    return err\n}","preventionTips":["Use a token with write scopes for toggling tasks.","Check the task is not locked by project rules before writing.","Back off on 429s; rapid repeated toggles hit rate limits.","Re-fetch task state on retry — the toggle recomputes Completed from fresh data."],"tags":["asana","api","task","update","permissions"],"backgroundTag":"api-write-permission-denied","analyzedSha":"bb838c1ccb0f0f3223690df44afdec663d622881","analyzedAt":"2026-09-03T17:02:45.030Z","contentChangedAt":"2026-09-03T17:02:45.030Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}