{"record":{"id":"3386859d7c371f74","repo":"rclone/rclone","slug":"total-length-of-command-line-and-environment-varia","errorCode":null,"errorMessage":"total length of command line and environment variables exceeds limit","messagePattern":"total length of command line and environment variables exceeds limit","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"fs/rc/js/wasm_exec.js","lineNumber":627,"sourceCode":"\n      const keys = Object.keys(this.env).sort();\n      keys.forEach((key) => {\n        argvPtrs.push(strPtr(`${key}=${this.env[key]}`));\n      });\n      argvPtrs.push(0);\n\n      const argv = offset;\n      argvPtrs.forEach((ptr) => {\n        this.mem.setUint32(offset, ptr, true);\n        this.mem.setUint32(offset + 4, 0, true);\n        offset += 8;\n      });\n\n      // The linker guarantees global data starts from at least wasmMinDataAddr.\n      // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.\n      const wasmMinDataAddr = 4096 + 8192;\n      if (offset >= wasmMinDataAddr) {\n        throw new Error(\n          \"total length of command line and environment variables exceeds limit\",\n        );\n      }\n\n      this._inst.exports.run(argc, argv);\n      if (this.exited) {\n        this._resolveExitPromise();\n      }\n      await this._exitPromise;\n    }\n\n    _resume() {\n      if (this.exited) {\n        throw new Error(\"Go program has already exited\");\n      }\n      this._inst.exports.resume();\n      if (this.exited) {\n        this._resolveExitPromise();","sourceCodeStart":609,"sourceCodeEnd":645,"githubUrl":"https://github.com/rclone/rclone/blob/f0b210a886ddc6171c92b6e21520dd890c3f2d21/fs/rc/js/wasm_exec.js#L609-L645","documentation":"Before starting the Go program, wasm_exec.js copies argv strings and environment variables into the WASM linear memory starting at address 0. The Go linker guarantees real global data begins at wasmMinDataAddr = 4096 + 8192 = 12288 bytes; if the argv/env block would reach that address it would overwrite global data, so run() aborts with this error instead of corrupting memory.","triggerScenarios":"Passing a Go instance with a very large go.argv array (this.argv = [\"js\"] by default), a huge go.env dictionary, or a combination whose encoded bytes (each string + NUL + 4-byte length + pointer table) total >= 12288 bytes. Each entry costs roughly len(string)+1 plus 8 bytes of pointer slot plus a 4-byte size field.","commonSituations":"Forwarding an entire process environment into go.env (e.g. go.env = process.env when the CI/secret-laden environment is enormous), passing long argument lists, or base64/huge tokens in env vars. Rare in normal use; appears in wrapper harnesses that bulk-copy environments.","solutions":["Trim go.env to only the variables the Go program needs instead of copying process.env wholesale","Shorten or remove oversized argv entries and env values (drop base64 blobs, certs, tokens from env if unused)","If genuinely more space is needed, rebuild the Go WASM module with a linker flag raising the data start (see cmd/link -W gclicated // in practice: raise wasmMinDataAddr in both the toolchain and this file consistently) - last resort, requires keeping wasmMinDataAddr in sync with cmd/link/internal/ld/data.go"],"exampleFix":"// before\ngo.env = process.env; // hundreds of vars, incl. huge CI secrets\nawait go.run(instance); // throws: exceeds limit\n\n// after\ngo.env = { PATH: process.env.PATH, HOME: process.env.HOME };\nawait go.run(instance);","handlingStrategy":"validation","validationCode":"// Before go.run(instance): rough budget check (limit is 12288 bytes of argv+env)\nconst encoded = (s) => s.length + 1 + 8 /* ptr slot */ + 4 /* size field */;\nconst total = go.argv.reduce((n, s) => n + encoded(s), 0) +\n              Object.entries(go.env).reduce((n, [k, v]) => n + encoded(k + '=' + v), 0);\nif (total >= 12288) throw new Error(`argv/env too large: ${total} >= 12288 bytes`);","typeGuard":null,"tryCatchPattern":"try { await go.run(instance); } catch (e) { if (/command line and environment/.test(e.message)) { go.env = pickNeededVars(go.env); /* retry with trimmed env */ } else throw e; }","preventionTips":["Never assign go.env = process.env wholesale; allow-list the variables the Go program reads","Keep argv short; pass bulky data via files or stdin instead of command-line arguments"],"tags":["wasm","javascript","limits","environment","rclone-js"],"backgroundTag":null,"analyzedSha":"f0b210a886ddc6171c92b6e21520dd890c3f2d21","analyzedAt":"2026-08-15T09:36:35.826Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}