{"record":{"id":"0b30f4553a4cd1a3","repo":"paperclipai/paperclip","slug":"daytona-syncout-refusing-unparseable-hardlink-entr","errorCode":null,"errorMessage":"Daytona syncOut refusing unparseable hardlink entry: ${line}","messagePattern":"Daytona syncOut refusing unparseable hardlink entry: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/daytona/src/file-sync.ts","lineNumber":215,"sourceCode":"  });\n  const lines = stdout.split(\"\\n\").filter((line) => line.trim().length > 0);\n  for (const line of lines) {\n    // GNU tar -tvf: \"<perms> <owner>/<group> <size> <date> <time> <name>[ -> target]\".\n    const match = line.match(/^(\\S+)\\s+\\S+\\s+\\d+\\s+\\S+\\s+\\S+\\s+(.*)$/);\n    if (!match) {\n      throw new Error(`Daytona syncOut refusing tarball with an unparseable entry listing: ${line}`);\n    }\n    const typeFlag = match[1][0];\n    let name = match[2];\n    let linkTarget: string | null = null;\n    if (typeFlag === \"l\") {\n      const idx = name.indexOf(\" -> \");\n      if (idx === -1) throw new Error(`Daytona syncOut refusing unparseable symlink entry: ${line}`);\n      linkTarget = name.slice(idx + \" -> \".length);\n      name = name.slice(0, idx);\n    } else if (typeFlag === \"h\") {\n      const idx = name.indexOf(\" link to \");\n      if (idx === -1) throw new Error(`Daytona syncOut refusing unparseable hardlink entry: ${line}`);\n      linkTarget = name.slice(idx + \" link to \".length);\n      name = name.slice(0, idx);\n    }\n    const cleanName = name.replace(/\\/+$/, \"\");\n    if (cleanName.length > 0 && posixPathEscapes(cleanName)) {\n      throw new Error(`Daytona syncOut refusing tarball member that escapes the extraction dir: ${name}`);\n    }\n    if (linkTarget !== null) {\n      const resolved = path.posix.join(path.posix.dirname(cleanName), linkTarget);\n      if (path.posix.isAbsolute(linkTarget) || posixPathEscapes(resolved)) {\n        throw new Error(\n          `Daytona syncOut refusing tarball link whose target escapes the extraction dir: ${name} -> ${linkTarget}`,\n        );\n      }\n    }\n  }\n}\n","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/sandbox-providers/daytona/src/file-sync.ts#L197-L233","documentation":"Thrown by assertTarballEntriesConfined when a hardlink entry in a sandbox-authored tar archive cannot be parsed. The function parses GNU `tar -tvf` verbose output and expects hardlink members (typeFlag 'h') to contain the literal substring ' link to ' separating the link name from its target. This guard exists because the tar is produced by an untrusted sandbox and any unparseable entry fails closed to prevent path-traversal during host-side extraction.","triggerScenarios":"A syncOut directory download produces a tarball where a hardlink line in `tar -tvf` output does not match the expected '<perms> ... <name> link to <target>' format, or the ' link to ' separator is missing. Also triggered if the sandbox tar binary emits a non-GNU verbose format (e.g. BSD tar) for hardlinks.","commonSituations":"The sandbox image uses a non-GNU tar (BSD/detect-tar) that formats hardlinks differently; a corrupted tarball from a partially-written sync; a tar version that localizes or alters the ' link to ' wording; locale settings changing tar's output format.","solutions":["Ensure the sandbox image provides GNU tar so `tar -tvf` emits the standard '<name> link to <target>' hardlink format.","Re-run the syncOut operation to regenerate the tarball in case of transient corruption.","Inspect the offending `line` value in the error message to identify which tar binary/format produced it and adjust the sandbox image accordingly.","Avoid placing hardlinks in the synced source directory if the sandbox tar cannot be standardized."],"exampleFix":"// before: sandbox ships BSD tar producing 'hardlink' wording\n// after: install GNU tar in the sandbox image Dockerfile\nRUN apt-get update && apt-get install -y tar","handlingStrategy":"validation","validationCode":"function isGnuTarHardlinkLine(line: string): boolean {\n  // typeFlag 'h' must carry ' link to ' separator after the name\n  const m = line.match(/^(\\S+)\\s+\\S+\\s+\\d+\\s+\\S+\\s+\\S+\\s+(.*)$/);\n  if (!m) return false;\n  if (m[1][0] !== 'h') return true;\n  return m[2].includes(' link to ');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await extractHostTarball({ archivePath, localDir });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('unparseable hardlink entry')) {\n    // sandbox tar format unsupported; rebuild archive with GNU tar\n  }\n  throw e;\n}","preventionTips":["Standardize the sandbox image on GNU tar so hardlink listings always use ' link to '.","Avoid hardlinks in synced source trees when the sandbox tar format is not guaranteed.","Pre-validate the tar listing format in the sandbox before transfer."],"tags":["daytona","file-sync","tar","security","syncout"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}