wtfutil/wtf · error

error updating task: %s

Error message

error updating task: %s

What it means

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.

Source

Thrown at modules/asana/client.go:134

	err := t.Fetch(client)
	if err != nil {
		return fmt.Errorf("error fetching task: %s", err)
	}

	updateReq := &asana.UpdateTaskRequest{}

	if *t.Completed {
		f := false
		updateReq.Completed = &f
	} else {
		t := true
		updateReq.Completed = &t
	}

	err = t.Update(client, updateReq)
	if err != nil {
		return fmt.Errorf("error updating task: %s", err)
	}

	return nil
}

func processFetchedTasks(client *asana.Client, fetchedTasks *[]*asana.Task, taskItems *[]*TaskItem, uidToName *map[string]string, mode, projectId, uid string) {

	for _, task := range *fetchedTasks {
		switch {
		case strings.HasSuffix(mode, "_all"):
			if task.Assignee != nil {
				// Check if we have already looked up this user
				if assigneeName, ok := (*uidToName)[task.Assignee.ID]; ok {
					task.Assignee.Name = assigneeName
				} else {
					// We haven't looked up this user before, perform the lookup now
					assigneeName, err := getOtherUserEmail(client, task.Assignee.ID)
					if err != nil {

View on GitHub (pinned to bb838c1ccb)

Solutions

  1. Verify the token/PAT has write scopes (OAuth apps need write scope for tasks).
  2. Confirm the task is not restricted by project rules or permissions in Asana.
  3. Check the wrapped HTTP status: 403 => permissions, 401 => re-auth, 429 => back off and retry the toggle.
  4. Retry the operation; it is idempotent (toggle recomputes from freshly fetched state).

Example fix

// before
err = t.Update(client, updateReq)
if err != nil {
    return fmt.Errorf("error updating task: %s", err)
}
// after
err = t.Update(client, updateReq)
if err != nil {
    return fmt.Errorf("error updating task %s: %w", taskId, err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm write access before toggling
u, err := client.CurrentUser()
if err != nil {
    return fmt.Errorf("token invalid: %w", err)
}
// ensure token has write scopes; read-only PATs will fail on Update

Try / catch

err := mod.Toggle(taskId)
if err != nil {
    if strings.Contains(err.Error(), "error updating task") {
        log.Printf("update rejected for %s; check write scopes and project rules: %v", taskId, err)
        return err // surface to caller; state is unchanged
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03). Data as JSON: /api/errors/fc0c9416f37845bf. Report an issue: GitHub.