{"record":{"id":"d0539a682e021cc8","repo":"swc-project/swc","slug":"invalid-attempt-to-iterate-non-iterable-instance","errorCode":null,"errorMessage":"Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.","messagePattern":"Invalid attempt to iterate non-iterable instance\\.\nIn order to be iterable, non-array objects must have a \\[Symbol\\.iterator\\]\\(\\) method\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_transforms_base/src/helpers/generated/_create_for_of_iterator_helper_loose.rs","lineNumber":27,"sourceCode":"    #[cfg(feature = \"inline-helpers\")]\n    source: r#\"function _create_for_of_iterator_helper_loose(o, allowArrayLike) {\n    var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"];\n\n    if (it) return (it = it.call(o)).next.bind(it);\n    // Fallback for engines without symbol support\n    if (Array.isArray(o) || (it = _unsupported_iterable_to_array(o)) || allowArrayLike && o && typeof o.length === \"number\") {\n        if (it) o = it;\n\n        var i = 0;\n\n        return function() {\n            if (i >= o.length) return { done: true };\n\n            return { done: false, value: o[i++] };\n        };\n    }\n\n    throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\n\"#,\n    #[cfg(feature = \"inline-helpers\")]\n    deps: super::HelperBitmap::from_bits(0x00000004000000000000020000000008),\n};\n\n#[cfg(feature = \"inline-helpers\")]\npub fn stmts() -> &'static [swc_ecma_ast::Stmt] {\n    static STMTS: once_cell::sync::Lazy<Vec<swc_ecma_ast::Stmt>> =\n        once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path));\n    &STMTS\n}\n","sourceCodeStart":9,"sourceCodeEnd":40,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_transforms_base/src/helpers/generated/_create_for_of_iterator_helper_loose.rs#L9-L40","documentation":"The napi `minify`/`minify_sync` entry point accepts either raw code or a JSON map of filename to code; the caller signals the JSON form with the `is_json: bool` flag. When is_json is true, MinifyTarget::Json deserializes the input with serde_json::from_str(...).expect(\"Invalid JSON\"), so malformed JSON panics the Rust side instead of returning a structured napi error. The panic is surfaced by napi-rs as a JS exception with the message 'Invalid JSON'.","triggerScenarios":"Calling minifySync(code, opts, true, extras) (or the async minify) where `code` is not a valid JSON object of shape { [filename]: string } - e.g. raw JS source passed while is_json=true, truncated JSON buffers, single quotes, trailing commas, or a JSON object with non-string values.","commonSituations":"Mixing up argument order or the boolean flag when migrating from @swc/core to the lower-level binding_core_node API; passing a filename instead of a JSON map; JSON.stringify omissions when the map is built manually; a second assertion in the same function also fires when the map has more than one entry.","solutions":["If you have plain source code, call minifySync(code, opts, false, extras) - the third argument selects the single-string mode.","If you want a filename attached, pass JSON.stringify({ 'input.js': code }) as the first argument and keep is_json=true.","Ensure the JSON map has exactly one entry - the next line asserts codes.len() == 1 ('swc.minify does not support concatting multiple files yet').","Validate/parse the JSON in JS before calling the binding so you get a normal SyntaxError with position instead of a Rust panic."],"exampleFix":"// before: raw code passed with is_json=true -> panic 'Invalid JSON'\nconst out = minifySync(code, opts, true, { mangleNameCache: null });\n\n// after: plain code mode\nconst out = minifySync(code, opts, false, { mangleNameCache: null });\n// or: single-entry filename map\nconst out = minifySync(JSON.stringify({ 'input.js': code }), opts, true, {\n  mangleNameCache: null,\n});","handlingStrategy":"validation","validationCode":"// Validate the JSON map before hitting the Rust binding:\nfunction toMinifyJson(filename, code) {\n  const map = { [filename]: code };\n  const json = JSON.stringify(map); // throws SyntaxError early if you built it wrong\n  const parsed = JSON.parse(json);\n  const entries = Object.entries(parsed);\n  if (entries.length !== 1 || typeof entries[0][1] !== 'string') {\n    throw new TypeError('expected exactly one { [file]: code } entry');\n  }\n  return json;\n}\nconst out = minifySync(toMinifyJson('input.js', code), opts, true, {\n  mangleNameCache: null,\n});","typeGuard":"function isMinifyJsonTarget(v: unknown): v is Record<string, string> {\n  return (\n    typeof v === 'object' &&\n    v !== null &&\n    !Array.isArray(v) &&\n    Object.keys(v).length === 1 &&\n    Object.values(v).every((x) => typeof x === 'string')\n  );\n}","tryCatchPattern":"try {\n  out = minifySync(json, opts, true, extras);\n} catch (e) {\n  // napi surfaces the Rust panic as a JS Error with message 'Invalid JSON'\n  if (/Invalid JSON/.test(String(e?.message))) {\n    throw new SyntaxError(`minify input is not a single-entry JSON map: ${json.slice(0, 80)}`);\n  }\n  throw e;\n}","preventionTips":["Always build the map with JSON.stringify({ [filename]: code }) instead of hand-concatenating strings.","Keep the is_json flag paired with the input shape: string code -> false, JSON map -> true.","Pin the binding version and read its .d.ts before upgrading - the boolean arg position has confused migrations."],"tags":["swc","napi","minify","json","node-bindings","panic"],"backgroundTag":"invalid-json-input","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}