{"record":{"id":"b39806fbe81a2d48","repo":"awslabs/llrt","slug":"failed-to-unmap-memory","errorCode":null,"errorMessage":"Failed to unmap memory","messagePattern":"Failed to unmap memory","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"llrt/src/main.c","lineNumber":277,"sourceCode":"\n  int outputFd = memfd_create_syscall(appname, 0);\n  if (outputFd == -1)\n  {\n    err(1, \"Could not create memfd\");\n  }\n\n  char *uncompressedData;\n  uint32_t uncompressedSize;\n\n  decompress(&uncompressedData, &uncompressedSize, outputFd);\n\n  double t1 = micro_seconds();\n  logInfo(\"Runtime starting\\n\");\n  logInfo(\"Extraction time: %10.4f ms\\n\", (t1 - t0) / 1000.0);\n\n  if (munmap(uncompressedData, uncompressedSize) == -1)\n  {\n    err(1, \"Failed to unmap memory\");\n  }\n\n  double t2 = micro_seconds();\n  logInfo(\"Extraction + write time: %10.4f ms\\n\", (t2 - t0) / 1000.0);\n\n  char **new_argv = malloc((size_t)(argc + 1) * sizeof *new_argv);\n  for (uint8_t i = 0; i < argc; ++i)\n  {\n    if (i == 0)\n    {\n      size_t length = strlen(appname) + 2;\n      new_argv[i] = malloc(length);\n      memcpy(new_argv[i], \"/\", 1);\n      memcpy(new_argv[i] + 1, appname, length);\n      setenv(\"_\", new_argv[i], true);\n    }\n    else\n    {","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/awslabs/llrt/blob/742fc00b82cbeaab1c1b76f0d706c302a5cbc306/llrt/src/main.c#L259-L295","documentation":"After the decompressed runtime has been fully written into the memfd mapping and executed-pending, main() calls munmap(uncompressedData, uncompressedSize) to release the mapping. This error means munmap returned -1. By this point extraction succeeded, so it signals address-space bookkeeping trouble rather than payload problems; the runtime still aborts with exit code 1.","triggerScenarios":"munmap fails because the (pointer, length) pair is not a valid mapping — practically only if decompress() returned a pointer/size inconsistent with the mmap done earlier (internal state bug), or if another thread/component already unmapped or altered the region. Address-length mismatch (size not matching the mapped extent) is the typical cause.","commonSituations":"Encountered only when llrt's own invariants are broken: a custom-patched build changed mmap flags (e.g. MAP_NORESERVE with alignment tricks), or someone instrumented/intercepted mmap/munmap (LD_PRELOAD, sanitizers) causing mismatched unmap calls.","solutions":["Run an unmodified official llrt binary — this failure indicates corrupted internal state, so rebuild cleanly from source.","Remove LD_PRELOAD interposers, sanitizers (ASAN/VALGRIND wrappers), or seccomp-notify tools that intercept mmap/munmap.","Check `dmesg`/strace output (`strace -f -e trace=mmap,munmap,llrt-binary`) to see the exact EINVAL/errno munmap returned.","Report the bug with the llrt version, kernel version, and strace log if it reproduces on a stock build."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Not preventable from outside; detect at supervisor level:\ntry {\n  child_process.execFileSync('./llrt', ['app.js']);\n} catch (e) {\n  if (e.status === 1 && /Failed to unmap memory/.test(String(e.stderr))) {\n    // rebuild from clean source / remove mmap-mutating interposers\n  }\n}","preventionTips":["Use official, unmodified llrt binaries — this error signals broken internal state.","Avoid LD_PRELOAD hooks or sanitizers that interpose mmap/munmap around the runtime.","If reproducible on a stock build, capture strace output and file a bug with kernel/version details.","Pin a known-good llrt release instead of custom-patched builds."],"tags":["munmap","memory","self-extraction","internal"],"backgroundTag":"munmap-failed","analyzedSha":"742fc00b82cbeaab1c1b76f0d706c302a5cbc306","analyzedAt":"2026-09-12T11:14:07.838Z","contentChangedAt":"2026-09-12T11:14:07.838Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}