AlistGo/alist · error

failed to parse task id: %w

Error message

failed to parse task id: %w

What it means

After a 202 response to a folder copy, the SJTU driver parses the body as a task-init response ({task_id}). This error fires when JSON unmarshal fails OR the parsed TaskId is 0. Note the bug: when TaskId==0 but unmarshal succeeded, err is nil, so the message renders '%!w(<nil>)' and the real cause is the zero/missing task_id field.

Source

Thrown at drivers/sjtu_netdisk/driver.go:549

			return &model.Object{
				Name:     srcObj.GetName(),
				Size:     srcObj.GetSize(),
				IsFolder: true,
				Modified: srcObj.ModTime(),
				Ctime:    time.Now(),
				Path:     targetPath,
			}, nil
		}

		// 202 Accepted:polling task status
		if resp.StatusCode() != http.StatusAccepted {
			return nil, fmt.Errorf("unexpected copy folder response: status=%d", resp.StatusCode())
		}

		var taskResp TaskInitResp
		if err := json.Unmarshal(resp.Body(), &taskResp); err != nil || taskResp.TaskId == 0 {
			return nil, fmt.Errorf("failed to parse task id: %w", err)
		}

		taskURL := fmt.Sprintf("%s/task/%s/%s/%d", API_URL, d.libraryId, d.spaceId, taskResp.TaskId)
		actualName := srcObj.GetName()
		taskDone := false

		for i := 0; i < 30 && !taskDone; i++ {
			select {
			case <-ctx.Done():
				return nil, ctx.Err()
			case <-time.After(1 * time.Second):
			}

			var taskStatus []TaskStatusItem
			_, pollErr := d.newClient().R().
				SetContext(ctx).
				SetQueryParam("access_token", d.accessToken).
				SetResult(&taskStatus).

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Retry the copy — transient 202-with-bad-body responses occur under server load
  2. Inspect the raw response body (log it) to see what the server actually returned
  3. If a proxy is involved, bypass it or fix its response handling
  4. If the field name changed upstream, update TaskInitResp's json tag in the driver
  5. Fix the driver to distinguish unmarshal failure from zero task id and include the body in the error

Example fix

// before
if err := json.Unmarshal(resp.Body(), &taskResp); err != nil || taskResp.TaskId == 0 {
    return nil, fmt.Errorf("failed to parse task id: %w", err)
}
// after
if err := json.Unmarshal(resp.Body(), &taskResp); err != nil {
    return nil, fmt.Errorf("failed to parse task id: %w, body: %s", err, resp.String())
}
if taskResp.TaskId == 0 {
    return nil, fmt.Errorf("task id missing in response body: %s", resp.String())
}
Defensive patterns

Strategy: retry

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to parse task id") {
    // body was empty/reshaped or task_id was 0; a fresh copy gets a new task
    return retryFolderCopyOnce()
}

Prevention

When it happens

Trigger: Server returns 202 with an empty or differently-shaped body (e.g. an error page from a proxy), or a JSON without a usable task_id field; also any body where task_id is absent/0.

Common situations: Reverse proxy intercepting the 202 and rewriting the body; API version change renaming the task id field; server acknowledging but failing to schedule the task.

Understand the failure class

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/e83cad33b94c6cab. Report an issue: GitHub.