{"record":{"id":"a6a673e67eb995f8","repo":"denoland/deno","slug":"abort-err","errorCode":"ABORT_ERR","errorMessage":"The operation was aborted","messagePattern":"The operation was aborted","errorType":"exception","errorClass":"AbortError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/fs.ts","lineNumber":701,"sourceCode":"    const data = await op_fs_read_file_async(\n      path,\n      cancelRid,\n      flagsNumber,\n    );\n    return data;\n  } finally {\n    if (options?.signal) {\n      options.signal[abortSignal.remove](abortHandler);\n\n      // always throw the abort error when aborted\n      options.signal.throwIfAborted();\n    }\n  }\n}\n\nfunction readFileCheckAborted(signal: AbortSignal | undefined) {\n  if (signal?.aborted) {\n    throw new AbortError(undefined, { cause: signal.reason });\n  }\n}\n\nfunction readFileConcatBuffers(buffers: Uint8Array[]): Uint8Array {\n  let totalLen = 0;\n  for (let i = 0; i < buffers.length; ++i) {\n    totalLen += TypedArrayPrototypeGetByteLength(buffers[i]);\n  }\n\n  const contents = new Uint8Array(totalLen);\n  let n = 0;\n  for (let i = 0; i < buffers.length; ++i) {\n    const buf = buffers[i];\n    TypedArrayPrototypeSet(contents, buf, n);\n    n += TypedArrayPrototypeGetByteLength(buf);\n  }\n\n  return contents;","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/node/polyfills/fs.ts#L683-L719","documentation":"Thrown by the callback-style fs.readFile wrapper in Deno's node:fs polyfill when the AbortSignal passed via options.signal is aborted. The finally block removes the abort handler and calls signal.throwIfAborted(), so an aborted readFile always rejects with an AbortError (code ABORT_ERR) instead of a partial result. This matches Node semantics: cancelling the read is an error, not a silent success.","triggerScenarios":"Calling fs.readFile(path, { signal }, cb) or fs.promises.readFile(path, { signal }) and calling controller.abort() while the read is in flight; also aborting the controller before the promise settles (throwIfAborted re-fires in the finally block).","commonSituations":"Request handlers that race file reads against client disconnects; download timeouts that share one AbortController across fetch and fs reads; reusing an already-aborted controller for a retry loop.","solutions":["Catch the error and branch on err.name === 'AbortError' (or err.code === 'ABORT_ERR') to treat it as cancellation, not failure","Check controller.signal.aborted before starting the read when the controller may already be cancelled","Use a fresh AbortController per read instead of reusing one shared controller","If you never intend to cancel, remove the signal option"],"exampleFix":"// before\nconst data = await fs.promises.readFile(path, { signal }); // throws AbortError uncaught\n\n// after\ntry {\n  const data = await fs.promises.readFile(path, { signal });\n} catch (err) {\n  if (err.name === 'AbortError') return; // cancelled on purpose\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":"if (signal?.aborted) {\n  // do not start the read; it would immediately throw AbortError\n  return;\n}","typeGuard":"const isAbortError = (e: unknown): e is Error =>\n  e instanceof Error && (e as Error & { code?: string }).code === 'ABORT_ERR';","tryCatchPattern":"try {\n  const data = await fs.promises.readFile(path, { signal });\n} catch (err) {\n  if (err instanceof Error && err.name === 'AbortError') return; // intentional cancel\n  throw err;\n}","preventionTips":["Check signal.aborted before each readFile when reusing one controller in loops","Use a dedicated AbortController per file operation so unrelated aborts do not cascade","Treat AbortError as control flow (name === 'AbortError'), never as a generic failure"],"tags":["node-compat","filesystem","abort","async"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}