deepseek-ai/deepseek-harness · error · AttachmentError

ATTACHMENT_WRITE_FAILED

ATTACHMENT_WRITE_FAILED

Error message

Image normalization did not produce a single-frame 8-bit sRGB image with matching metadata.

What it means

After normalizeImage encodes a normalized variant, verifyNormalizedImage re-detects that output and asserts the normalization contract: same media type and dimensions as encoded, single-frame, no retained EXIF/ICC/metadata, 8-bit 'uchar' depth, 'srgb' colour space, and alpha compatible with the source. A mismatch means sharp/libvips produced output violating the invariant — an encoder or storage fault routed as ATTACHMENT_WRITE_FAILED, not a caller-input problem.

Source

Thrown at packages/attachment/attachment-local/src/normalization.ts:108

  }
  return true
}

/** Assert that a normalized output is an 8-bit sRGB/sRGBA single-frame image with matching facts. */
async function verifyNormalizedImage(
  image: NormalizedImage,
  expectedAlpha: boolean | undefined,
): Promise<NormalizedImage> {
  const detected = await detectImage(image.data)
  if (detected.mediaType !== image.mediaType
    || detected.width !== image.width
    || detected.height !== image.height
    || detected.animated
    || detected.carriesMetadata
    || detected.depth !== 'uchar'
    || detected.space !== 'srgb'
    || !encodedAlphaIsCompatible(expectedAlpha, detected)) {
    throw new AttachmentError(
      'Image normalization did not produce a single-frame 8-bit sRGB image with matching metadata.',
      'ATTACHMENT_WRITE_FAILED',
    )
  }
  return image
}

/** Build one fixed-size, oriented, metadata-free sRGB pipeline from submitted bytes. */
function preparedPipeline(data: Uint8Array, width: number, height: number): Sharp {
  return sharp(data, { failOn: 'error', limitInputPixels: false })
    .rotate()
    .toColourspace('srgb')
    .resize({ width, height, fit: 'inside', withoutEnlargement: true })
}

/** Dimensions after the long edge is capped without changing aspect ratio. */
function initialDimensions(detected: DetectedImage, maxDimension: number): { width: number; height: number } {
  const scale = Math.min(1, maxDimension / Math.max(detected.width, detected.height))

View on GitHub (pinned to b150a551b8)

Solutions

  1. Re-encode the source externally to a clean, metadata-free 8-bit sRGB image and resubmit.
  2. Align the sharp/libvips version with the one this harness pins and retry.
  3. If reproducible on the pinned stack, report it upstream with the source image — this check exists to catch encoder regressions.

Example fix

// before
const normalized = await normalizeImage(data, detected, policy)

// after: pre-clean problem sources so the encode path starts from 8-bit sRGB
const clean = await sharp(data).rotate().toColourspace('srgb').png().toBuffer()
const normalized = await normalizeImage(clean, await detectImage(clean), policy)
Defensive patterns

Strategy: try-catch

Type guard

const isNormalizationFault = (e: unknown): boolean =>
  e instanceof Error && 'code' in e && (e as { code?: string }).code === 'ATTACHMENT_WRITE_FAILED'

Try / catch

try {
  const normalized = await normalizeImage(data, detected, policy)
} catch (error) {
  if (isNormalizationFault(error)) {
    // encoder/storage fault: surface for re-upload or an upstream report; same-bytes retry is futile
  }
  throw error
}

Prevention

When it happens

Trigger: normalizeImage returning an encode whose re-detection diverges: an encoder release that embeds an ICC profile or orientation tag, WebP dimension rounding differing from the encode info, a colourspace reported other than srgb, multi-frame output, or alpha dropped outside the tolerated all-opaque WebP case.

Common situations: sharp/libvips version drift after a dependency update changes metadata emission; platform libvips builds differing across Linux, macOS, and CI; usually deterministic for the same input and stack, so retries of the same bytes fail identically.

Related errors


AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24). Data as JSON: /api/errors/0ccb48d2153306d8. Report an issue: GitHub.