AlistGo/alist · error

delete offline tasks failed: %s

Error message

delete offline tasks failed: %s

What it means

Thrown by GuangYaPan's DeleteOfflineTasks after POST /cloudcollection/v2/delete_task succeeds at the HTTP layer but returns a non-success Msg. The server processed (or rejected) the batch deletion of task IDs; the trimmed server message is included. Note deletion is all-or-nothing from the caller's view — partial server-side success is not distinguishable here.

Source

Thrown at drivers/guangyapan/offline.go:129

	return resp.Data.List, nil
}

func (d *GuangYaPan) DeleteOfflineTasks(ctx context.Context, taskIDs []string, deleteFiles bool) error {
	if err := d.ensureAccessToken(ctx); err != nil {
		return err
	}
	if len(taskIDs) == 0 {
		return nil
	}

	var resp offlineDeleteResp
	if err := d.postAPI(ctx, "/cloudcollection/v2/delete_task", map[string]any{
		"taskIds": taskIDs,
	}, &resp); err != nil {
		return err
	}
	if !isSuccessMsg(resp.Msg) {
		return fmt.Errorf("delete offline tasks failed: %s", strings.TrimSpace(resp.Msg))
	}
	return nil
}

func (d OfflineResolveData) defaultName(fileURL string) string {
	if d.BTResInfo != nil && strings.TrimSpace(d.BTResInfo.FileName) != "" {
		return strings.TrimSpace(d.BTResInfo.FileName)
	}
	u, err := url.Parse(fileURL)
	if err == nil {
		name := strings.TrimSpace(stdpath.Base(u.Path))
		if name != "" && name != "." && name != "/" {
			if decoded, err := url.PathUnescape(name); err == nil {
				name = decoded
			}
			return name
		}
	}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Inspect resp.Msg for the server's reason (already-deleted vs. auth vs. batch-size errors).
  2. Re-list tasks (ListOfflineTasks) and filter out IDs that no longer exist before retrying the delete.
  3. Treat 'already deleted/not found' style messages as success (idempotent delete) at the caller level if the workflow allows.
  4. Split very large taskIDs batches into smaller chunks if the msg indicates a limit.

Example fix

// before
if err := d.DeleteOfflineTasks(ctx, taskIDs, true); err != nil { return err }

// after
if err := d.DeleteOfflineTasks(ctx, taskIDs, true); err != nil {
    if strings.Contains(err.Error(), "not exist") { // server-specific idempotency marker
        return nil // already gone; treat as success
    }
    return err
}
Defensive patterns

Strategy: validation

Validate before calling

// prune IDs against a fresh listing before deleting
list, err := d.ListOfflineTasks(ctx, "", 100)
if err != nil { return err }
live := make(map[string]bool)
for _, t := range list { live[t.TaskID] = true }
valid := taskIDs[:0]
for _, id := range taskIDs { if live[id] { valid = append(valid, id) } }
if len(valid) == 0 { return nil }

Try / catch

if err := d.DeleteOfflineTasks(ctx, ids, del); err != nil {
    if strings.Contains(err.Error(), "delete offline tasks failed") && isNotFoundMsg(err) {
        return nil // idempotent
    }
    return err
}

Prevention

When it happens

Trigger: Passing task IDs that were already deleted, expired, or belong to another account; sending a batch larger than the v2 endpoint accepts; token revoked between the listing call and the delete call.

Common situations: UI deletes a task twice (double-click, stale list refresh); concurrent deletion from another client between list and delete; retrying a delete that actually succeeded (the first attempt's response was lost).

Related errors


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