{"record":{"id":"d27b383e83a0ab3f","repo":"parcel-bundler/parcel","slug":"asset-has-an-ast-but-no-generate-method-is-availab","errorCode":null,"errorMessage":"Asset has an AST but no generate method is available on the transform","messagePattern":"Asset has an AST but no generate method is available on the transform","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/core/src/Transformation.js","lineNumber":692,"sourceCode":"      });\n    let results = await normalizeAssets(this.options, transfomerResult);\n\n    // Create generate and postProcess function that can be called later\n    asset.generate = (): Promise<GenerateOutput> => {\n      let publicAsset = new Asset(asset);\n      if (transformer.generate && asset.ast) {\n        let generated = transformer.generate({\n          asset: publicAsset,\n          ast: asset.ast,\n          options: pipeline.pluginOptions,\n          logger,\n          tracer,\n        });\n        asset.clearAST();\n        return Promise.resolve(generated);\n      }\n\n      throw new Error(\n        'Asset has an AST but no generate method is available on the transform',\n      );\n    };\n\n    let postProcess = transformer.postProcess;\n    if (postProcess) {\n      pipeline.postProcess = async (\n        assets: Array<UncommittedAsset>,\n      ): Promise<Array<UncommittedAsset> | null> => {\n        let results = await postProcess.call(transformer, {\n          assets: assets.map(asset => new MutableAsset(asset)),\n          config,\n          options: pipeline.pluginOptions,\n          resolve,\n          logger,\n          tracer,\n        });\n","sourceCodeStart":674,"sourceCodeEnd":710,"githubUrl":"https://github.com/parcel-bundler/parcel/blob/59484858a1a0bcbb71f74088956bb437a2db6505/packages/core/core/src/Transformation.js#L674-L710","documentation":"When a transformer produces an AST, Parcel later needs to turn that AST back into source code via the transformer's `generate()`. The code path checks `transformer.generate && asset.ast` first; if the asset holds an AST but the transformer has no `generate`, Parcel cannot serialize the AST and rejects it as a contract violation.","triggerScenarios":"A transformer returns/sets `ast` on the asset but does not implement a `generate({asset, ast, options})` method.","commonSituations":"Writing a custom transformer that parses to an AST for analysis but forgets the code-generation step.","solutions":["Implement `generate({asset, ast, options, logger})` on the transformer, returning `{content, map}`.","If you don't need an AST, don't set `ast` on the asset — return code directly.","Reuse an existing AST-capable transformer (e.g. `@parcel/transformer-js`) instead of a code-only one."],"exampleFix":"// before\nexport default new Transformer({\n  async transform({asset}) {\n    asset.ast = parse(await asset.getCode());\n    return [asset];\n  }\n});\n\n// after\nexport default new Transformer({\n  async transform({asset}) {\n    asset.ast = parse(await asset.getCode());\n    return [asset];\n  },\n  async generate({asset, ast, options}) {\n    return {content: generate(ast), map: undefined};\n  }\n});","handlingStrategy":"type-guard","validationCode":"// Only set ast when the transformer can generate from it.\nif (typeof transformer.generate === 'function') {\n  asset.ast = parsed;\n}","typeGuard":"function canGenerate(t: {generate?: Function}): boolean {\n  return typeof t.generate === 'function';\n}","tryCatchPattern":null,"preventionTips":["Implement generate() in any transformer that sets ast.","In tests, assert the transformer exposes generate before assigning ast."],"tags":["transformer","ast","plugin"],"backgroundTag":null,"analyzedSha":"59484858a1a0bcbb71f74088956bb437a2db6505","analyzedAt":"2026-08-13T04:06:35.925Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}