yikart/AiToEarn · info · DOMException

Upload canceled

Error message

Upload canceled

What it means

enqueueUpload throws an AbortError DOMException named 'Upload canceled' when the user cancels a task between fingerprint computation (computeFileFingerprint) and registering the task's md5. The queue keeps a canceledTasks set keyed by taskId; at each async checkpoint it re-checks membership and aborts so a canceled file never proceeds to upload. This is a normal, user-initiated control-flow signal, not a fault.

Source

Thrown at project/aitoearn-web/src/components/PublishDialog/compoents/PublishManageUpload/usePublishManageUpload.ts:196

            fileName: name,
            size: file.size ?? 0,
            type,
            status: UploadTaskStatusEnum.Hashing,
            progress: 0,
            createdAt: Date.now(),
            updatedAt: Date.now(),
          },
        },
      }))

      const promise = (async (): Promise<UploadResult> => {
        let currentMd5: string | undefined
        try {
          const md5 = computeFileFingerprint(file, name)
          currentMd5 = md5

          if (canceledTasks.has(taskId)) {
            throw new DOMException('Upload canceled', 'AbortError')
          }

          taskMd5Map.set(taskId, md5)

          finalizeTask(taskId, {
            md5,
            status: UploadTaskStatusEnum.Pending,
          })

          const cache = get().md5Cache[md5]
          if (cache) {
            const result: UploadResult = { ...cache, fromCache: true }
            finalizeTask(taskId, {
              status: UploadTaskStatusEnum.Success,
              progress: 100,
              fromCache: true,
            })
            return result

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Treat DOMException with name 'AbortError' and message 'Upload canceled' as an expected cancel signal: swallow it or update task state to 'canceled', do not surface it as an error toast.
  2. Ensure cancel actions set the task's UI status to canceled before/independent of the queue throwing, so the user sees consistent state.
  3. If you need the upload to proceed, do not add the taskId to canceledTasks; check membership only after the user confirms cancel.
  4. On unmount, clear pending tasks deliberately and suppress AbortError logging to avoid noisy console errors.

Example fix

// before
task.cancel = () => canceledTasks.add(taskId)
await enqueueUpload(file) // rejects with 'Upload canceled'

// after
try {
  await enqueueUpload(file)
}
catch (e) {
  if (e instanceof DOMException && e.name === 'AbortError') {
    updateTaskStatus(taskId, 'canceled')
    return
  }
  throw e
}
Defensive patterns

Strategy: try-catch

Validate before calling

// no cheap pre-check: the cancel can land at any async checkpoint
const isCanceled = (taskId: string) => canceledTasks.has(taskId)
if (isCanceled(taskId)) return // skip enqueue entirely when already canceled

Type guard

function isAbortError(e: unknown): e is DOMException {
  return e instanceof DOMException && e.name === 'AbortError'
}

Try / catch

try {
  await enqueueUpload(file)
}
catch (e) {
  if (isAbortError(e)) { markTaskCanceled(taskId); return }
  throw e
}

Prevention

When it happens

Trigger: Calling enqueueUpload and removing/canceling the task (adding its taskId to canceledTasks) while computeFileFingerprint(file, name) is still running, before taskMd5Map.set(taskId, md5) executes.

Common situations: User clicks remove/cancel on a file row in the publish manage upload list while the md5 fingerprint of a large file is being computed; rapid cancel after enqueue; component unmount cleanup canceling in-flight enqueues.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/ddb51a0881137e95. Report an issue: GitHub.