{"record":{"id":"86f2856c303982bc","repo":"evanw/esbuild","slug":"invalid-loader","errorCode":null,"errorMessage":"Invalid loader","messagePattern":"Invalid loader","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/api/api_impl.go","lineNumber":299,"sourceCode":"\t\treturn config.LoaderGlobalCSS\n\tcase LoaderJS:\n\t\treturn config.LoaderJS\n\tcase LoaderJSON:\n\t\treturn config.LoaderJSON\n\tcase LoaderJSX:\n\t\treturn config.LoaderJSX\n\tcase LoaderLocalCSS:\n\t\treturn config.LoaderLocalCSS\n\tcase LoaderNone:\n\t\treturn config.LoaderNone\n\tcase LoaderText:\n\t\treturn config.LoaderText\n\tcase LoaderTS:\n\t\treturn config.LoaderTS\n\tcase LoaderTSX:\n\t\treturn config.LoaderTSX\n\tdefault:\n\t\tpanic(\"Invalid loader\")\n\t}\n}\n\nfunc extractPathStyle(absPaths AbsPaths, flag AbsPaths) logger.PathStyle {\n\tif (absPaths & flag) != 0 {\n\t\treturn logger.AbsPath\n\t} else {\n\t\treturn logger.RelPath\n\t}\n}\n\nvar versionRegex = regexp.MustCompile(`^([0-9]+)(?:\\.([0-9]+))?(?:\\.([0-9]+))?(-[A-Za-z0-9]+(?:\\.[A-Za-z0-9]+)*)?$`)\n\nfunc validateFeatures(log logger.Log, target Target, engines []Engine) (compat.JSFeature, compat.CSSFeature, map[css_ast.D]compat.CSSPrefix, string) {\n\tif target == DefaultTarget && len(engines) == 0 {\n\t\treturn 0, 0, nil, \"\"\n\t}\n","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/pkg/api/api_impl.go#L281-L317","documentation":"validateLoader (pkg/api/api_impl.go:299) panics when a Loader value is not one of LoaderNone..LoaderTSX (the 17-constant iota in api.go). The function maps the public Loader to the internal config.Loader used for parsing a file extension or stdin; an unknown value means the parser cannot be selected, so esbuild aborts. Called from validateLoaders (per extension in BuildOptions.Loader), from StdinOptions.Loader, and from TransformOptions.Loader.","triggerScenarios":"Passing an out-of-range integer for any Loader field, deserializing Loader maps from a numeric wire format, or bridging a different esbuild version where the iota ordering or count differs (this enum is the longest of the set, so it is the most sensitive to renumbering).","commonSituations":"Re-vendoring esbuild and forgetting to regenerate a JS/Go bridge that maps loader names to numbers, persisted configs that store loader as an int, or a typo like `LoaderJSON5` (no such constant). Also triggered by a `Loader` map entry whose value was set to a stale constant after an upgrade removed it.","solutions":["Use only the api.Loader* constants; for unknown extensions default to api.LoaderDefault or api.LoaderNone.","Bounds-check decoded integers against 0..16 (LoaderTSX) before casting.","Store loader mappings keyed by name (\"js\",\"ts\",\"css\",...) and translate to constants at load.","After re-vendoring esbuild, regenerate any bridge/table code (js_table.ts) and rebuild all consumers."],"exampleFix":"// before\nopts := api.BuildOptions{Loader: map[string]api.Loader{\".custom\": api.Loader(40)}}\n\n// after\nopts := api.BuildOptions{Loader: map[string]api.Loader{\".custom\": api.LoaderText}}","handlingStrategy":"validation","validationCode":"func checkLoader(l api.Loader) error {\n    switch l {\n    case api.LoaderNone, api.LoaderBase64, api.LoaderBinary, api.LoaderCopy,\n        api.LoaderCSS, api.LoaderDataURL, api.LoaderDefault, api.LoaderEmpty,\n        api.LoaderFile, api.LoaderGlobalCSS, api.LoaderJS, api.LoaderJSON,\n        api.LoaderJSX, api.LoaderLocalCSS, api.LoaderText, api.LoaderTS, api.LoaderTSX:\n        return nil\n    }\n    return fmt.Errorf(\"invalid loader %d (want 0..%d)\", uint16(l), uint16(api.LoaderTSX))\n}\n\nfor ext, l := range opts.Loader {\n    if err := checkLoader(l); err != nil { return fmt.Errorf(\"loader for %q: %w\", ext, err) }\n}\nif opts.Stdin != nil {\n    if err := checkLoader(opts.Stdin.Loader); err != nil { return err }\n}","typeGuard":"func isValidLoader(l api.Loader) bool {\n    switch l {\n    case api.LoaderNone, api.LoaderBase64, api.LoaderBinary, api.LoaderCopy,\n        api.LoaderCSS, api.LoaderDataURL, api.LoaderDefault, api.LoaderEmpty,\n        api.LoaderFile, api.LoaderGlobalCSS, api.LoaderJS, api.LoaderJSON,\n        api.LoaderJSX, api.LoaderLocalCSS, api.LoaderText, api.LoaderTS, api.LoaderTSX:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Loader is the longest esbuild enum and the most fragile across versions; regenerate any bridge after each re-vendor.","Prefer named loader strings (\"js\",\"ts\",\"css\",...) in user config and translate to constants at the boundary.","Default unknown extensions to LoaderDefault or LoaderNone rather than a guessed number.","Add a test that iterates your Loader map and asserts each value is in range."],"tags":["esbuild","config","validation","panic","loader","enum"],"backgroundTag":null,"analyzedSha":"f6058f8364fe7ab91ca57a83e02577ed74c9cae4","analyzedAt":"2026-08-09T18:37:22.223Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}