{"id":"b607e45c54783ebc","repo":"vitest-dev/vitest","slug":"test-attachment-requires-body-or-path-to-be-se","errorCode":null,"errorMessage":"Test attachment requires \"body\" or \"path\" to be set. Both are missing.","messagePattern":"Test attachment requires \"body\" or \"path\" to be set\\. Both are missing\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/runtime/runner/artifact.ts","lineNumber":172,"sourceCode":"    test.promises = []\n  }\n  test.promises.push(promise)\n  return promise\n}\n\n/**\n * Validates and prepares a test attachment for serialization.\n *\n * This function ensures attachments have either `body` or `path` set (but not both), and converts `Uint8Array` bodies to base64-encoded strings for easier serialization.\n *\n * @param attachment - The attachment to validate and prepare\n *\n * @throws {TypeError} If neither `body` nor `path` is provided\n * @throws {TypeError} If both `body` and `path` are provided\n */\nexport function manageArtifactAttachment(attachment: TestAttachment): void {\n  if (attachment.body == null && !attachment.path) {\n    throw new TypeError(`Test attachment requires \"body\" or \"path\" to be set. Both are missing.`)\n  }\n  if (attachment.body && attachment.path) {\n    throw new TypeError(`Test attachment requires only one of \"body\" or \"path\" to be set. Both are specified.`)\n  }\n  if (attachment.path && attachment.bodyEncoding) {\n    throw new TypeError(`Test attachment with \"path\" should not have \"bodyEncoding\" specified.`)\n  }\n  // convert to a string so it's easier to serialise\n  if (attachment.body instanceof Uint8Array) {\n    attachment.body = encodeUint8Array(attachment.body)\n  }\n  if (attachment.body != null) {\n    attachment.bodyEncoding ??= 'base64'\n  }\n}\n","sourceCodeStart":154,"sourceCodeEnd":188,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/runtime/runner/artifact.ts#L154-L188","documentation":"`manageArtifactAttachment` (`artifact.ts:172`) validates every attachment carries a payload: at least one of `body` (inline string/`Uint8Array`) or `path` (a file reference) must be set. An attachment with neither — e.g. `{ name: 'log' }` — is rejected with this `TypeError` before serialization, since there'd be nothing to attach.","triggerScenarios":"`recordArtifact(task, { type: '...', attachments: [{}] })`; `attachments: [{ name: 'x', contentType: 'text/plain' }]` with no body/path; building attachments programmatically and ending up with empty objects.","commonSituations":"Conditionally populating attachment fields and forgetting the payload; copy-paste leaving body/path off; an attachment builder that returns `{}` on a missing file.","solutions":["Set `attachment.body` (string or `Uint8Array`) OR `attachment.path` (absolute/relative filepath).","If the payload is optional, skip pushing that attachment entirely instead of pushing an empty one.","Validate attachments before calling `recordArtifact` (see validationCode)."],"exampleFix":"// before\nrecordArtifact(task, {\n  type: 'report',\n  attachments: [{ name: 'log' }],\n})\n\n// after\nrecordArtifact(task, {\n  type: 'report',\n  attachments: [{ name: 'log', path: '/tmp/run.log' }],\n})","handlingStrategy":"validation","validationCode":"// Validate each attachment has a payload before recording.\nfunction validateAttachments(attachments: TestAttachment[]) {\n  for (const a of attachments) {\n    if (a.body == null && !a.path) {\n      throw new TypeError(`Attachment \"${a.name ?? '<unnamed>'}\" needs body or path`)\n    }\n  }\n}\nvalidateAttachments(artifact.attachments ?? [])\nawait recordArtifact(task, artifact)","typeGuard":"function hasAttachmentPayload(a: { body?: unknown; path?: string }): boolean {\n  return a.body != null || Boolean(a.path)\n}","tryCatchPattern":"try {\n  await recordArtifact(task, artifact)\n} catch (e) {\n  if (e instanceof TypeError && /requires \"body\" or \"path\"/.test(e.message)) {\n    // add a body or path to each empty attachment\n  } else throw e\n}","preventionTips":["Always set either body or path on every attachment.","Skip pushing attachments whose payload is missing rather than pushing empty objects.","Centralize attachment construction in a builder that enforces the payload."],"tags":["artifacts","attachment","validation","typeerror"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}