awslabs/llrt · critical

Failed to set file size

Error message

Failed to set file size

What it means

During decompression of the embedded (self-extracted) payload, llrt calls ftruncate(outputFd, *uncompressedSize) to pre-size the output memfd to the expected uncompressed size before mmap'ing it. This err(1) means the ftruncate syscall returned -1, so the output file could not be sized. Without a correctly sized file the subsequent shared mmap of the decompressed data is impossible, so the runtime aborts immediately.

Solutions

  1. Check sandbox/seccomp/container settings and allow the ftruncate syscall (e.g. adjust seccomp profile or AppArmor/SELinux policy).
  2. Verify the kernel is Linux with memfd/ftruncate support; run on a standard glibc/musl Linux environment.
  3. Rebuild llrt with debugging (logInfo) to confirm the memfd_create_syscall succeeded and outputFd is valid.
  4. Check RLIMIT_FSIZE (ulimit -f) is not set to 0 for the process.
Defensive patterns

Strategy: validation

Validate before calling

// Before deploying, smoke-test the binary in the target environment:
// it must run in a sandbox allowing ftruncate on memfd.
import { execFileSync } from 'node:child_process';
try {
  execFileSync('./llrt', ['-v'], { stdio: 'ignore' });
} catch (e) {
  throw new Error('llrt cannot start here (ftruncate/memfd blocked): ' + e.message);
}

Try / catch

// err(1) exits the process — it cannot be caught inside llrt.
// Catch at the supervisor level:
try {
  child_process.execFileSync('./llrt', ['app.js']);
} catch (e) {
  if (e.status === 1 && /Failed to set file size/.test(String(e.stderr))) {
    // fall back to a non-self-extracting runtime or fix the sandbox
  }
}

Prevention

When it happens

Trigger: ftruncate on the memfd created in main fails — practically only when the file descriptor outputFd is invalid (memfd creation silently broken), the fd was closed, or the process hits RLIMIT_FSIZE / runs on a filesystem or kernel lacking ftruncate support for the fd. Triggered by running the binary at all, since decompress() is called from main before any user code.

Common situations: Running the llrt binary in a hardened sandbox (seccomp filter blocking ftruncate), inside containers with restricted syscall allowlists, or on exotic kernels/fork servers where fd 0-state is manipulated before entry. Extremely rare on normal Linux.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of awslabs/llrt@742fc00b82 (2026-09-12). Data as JSON: /api/errors/9591829ac519bf6e. Report an issue: GitHub.

Appendix: source

Thrown at llrt/src/main.c:205

  char *uncompressed;
  uint8_t *compressedData;

  pthread_t threads[parts];

  if (parts > 1)
  {
    logInfo("Decompressing using %d threads\n", parts);
  }
  else
  {
    logInfo("Decompressing\n");
  }

  readData(data, parts, &inputSizes, &outputSizes, &compressedData, uncompressedSize);

  if (ftruncate(outputFd, *uncompressedSize) == -1)
  {
    err(1, "Failed to set file size");
  }

  uncompressed = mmap(NULL, *uncompressedSize, PROT_READ | PROT_WRITE, MAP_SHARED, outputFd, 0);
  if (uncompressed == MAP_FAILED || !uncompressed)
  {
    err(1, "Memory mapping failed: Unable to map %u bytes. Make sure you have enough memory available", *uncompressedSize);
  }

  DecompressThreadArgs args[parts];
  for (uint32_t i = 0; i < parts; i++)
  {
    args[i].inputBuffer = compressedData + inputOffset;
    args[i].outputBuffer = uncompressed + outputOffset;
    args[i].srcSize = inputSizes[i];
    args[i].dstSize = outputSizes[i];
    args[i].id = i;
    inputOffset += inputSizes[i];
    outputOffset += outputSizes[i];

View on GitHub (pinned to 742fc00b82)