{"record":{"id":"524069b720a8248e","repo":"apache/echarts","slug":"maintype-type-should-be-specified","errorCode":null,"errorMessage":"{mainType}.type should be specified.","messagePattern":"(.+?)\\.type should be specified\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/util/clazz.ts","lineNumber":289,"sourceCode":"                container[componentTypeInfo.sub] = clz;\n            }\n        }\n        return clz;\n    };\n\n    target.getClass = function (\n        mainType: ComponentMainType,\n        subType?: ComponentSubType,\n        throwWhenNotFound?: boolean\n    ): Constructor {\n        let clz = storage[mainType];\n\n        if (clz && (clz as SubclassContainer)[IS_CONTAINER]) {\n            clz = subType ? (clz as SubclassContainer)[subType] : null;\n        }\n\n        if (throwWhenNotFound && !clz) {\n            throw new Error(\n                !subType\n                    ? mainType + '.' + 'type should be specified.'\n                    : 'Component ' + mainType + '.' + (subType || '') + ' is used but not imported.'\n            );\n        }\n\n        return clz as Constructor;\n    };\n\n    target.getClassesByMainType = function (componentType: ComponentFullType): Constructor[] {\n        const componentTypeInfo = parseClassType(componentType);\n\n        const result: Constructor[] = [];\n        const obj = storage[componentTypeInfo.main];\n\n        if (obj && (obj as SubclassContainer)[IS_CONTAINER]) {\n            zrUtil.each(obj as SubclassContainer, function (o, type) {\n                type !== IS_CONTAINER && result.push(o as Constructor);","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/apache/echarts/blob/30076aedcd7b7f65d8dd8e8d9ece46ce778133a3/src/util/clazz.ts#L271-L307","documentation":"Thrown by the class-manager's `getClass(mainType, subType, throwWhenNotFound)` in clazz.ts:289. It fires only when the caller passes `throwWhenNotFound === true`, the lookup found no registered class under `mainType`, AND no `subType` was supplied (the `!subType` branch). The interpolated message `mainType + '.type should be specified.'` is the library's way of saying \"no class is registered for component main type X\". Unlike most dev errors in this file, this throw is NOT gated by `__DEV__` — it is produced whenever the internal caller marks the lookup mandatory, so it can occur in production bundles.","triggerScenarios":"An internal call like `getClass('grid', undefined, true)` (or any single-class main type such as `xAxis`, `singleAxis`, `polar`) where that component main type was never registered. The typical cause in user code is an on-demand build (`echarts/core`) that references a component whose module was omitted from `echarts.use([...])`, so `storage[mainType]` is empty.","commonSituations":"Migrating from the full `echarts` import to tree-shaken `echarts/core` and leaving some components (grid, polar, radar, etc.) out of `.use()`; using a trimmed bundle (`echarts.simple`/`echarts.common`) that excludes the referenced component; a typo in a component's `type` field that resolves to an unregistered main type; a custom component whose `registerClass`/install was never invoked.","solutions":["Register the missing component named in the message: e.g. `import { GridComponent } from 'echarts/components'; echarts.use([GridComponent]);` (substitute the mainType from the error).","Audit your `echarts.use([...])` list against every component `type` / coordinate-system component referenced in your option.","If you did not intend to use on-demand imports, switch to the full bundle: `import * as echarts from 'echarts';` which registers all built-ins.","Check the spelling of the offending `type` value in your option against the registered component names."],"exampleFix":"// before\nimport * as echarts from 'echarts/core';\nimport { BarChart } from 'echarts/charts';\necharts.use([BarChart]); // GridComponent missing -> 'grid.type should be specified.'\nconst option = { xAxis: { type: 'category' }, yAxis: {}, series: [{ type: 'bar' }] };\n\n// after\nimport * as echarts from 'echarts/core';\nimport { BarChart } from 'echarts/charts';\nimport { GridComponent } from 'echarts/components';\necharts.use([BarChart, GridComponent]);\nconst option = { xAxis: { type: 'category' }, yAxis: {}, series: [{ type: 'bar' }] };","handlingStrategy":"validation","validationCode":"// Validate that every component main type referenced by the option is registered,\n// by attempting a throwaway setOption on a hidden instance and catching the error.\nfunction validateRegistrations(echartsRef, option) {\n  const probe = echartsRef.init(document.createElement('div'));\n  try {\n    probe.setOption(option, true);\n  } catch (e) {\n    throw new Error('Unregistered component detected before render: ' + e.message);\n  } finally {\n    probe.dispose();\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Maintain a single `echarts.use([...])` registry module and treat it as the source of truth for supported component types.","When migrating to `echarts/core`, diff your old full-bundle usage against the new `.use()` list component by component.","Add a startup smoke test that calls `setOption` with a minimal option per supported component type so missing registrations fail in CI, not in production."],"tags":["class-registry","on-demand-import","component","configuration"],"backgroundTag":null,"analyzedSha":"30076aedcd7b7f65d8dd8e8d9ece46ce778133a3","analyzedAt":"2026-08-12T12:42:28.134Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}