{"record":{"id":"304fe38d0418d8f4","repo":"videojs/video.js","slug":"tech-name-must-be-a-tech","errorCode":null,"errorMessage":"Tech ${name} must be a Tech","messagePattern":"Tech (.+?) must be a Tech","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/js/tech/tech.js","lineNumber":1018,"sourceCode":"           component === Tech;\n  }\n\n  /**\n   * Registers a `Tech` into a shared list for videojs.\n   *\n   * @param {string} name\n   *        Name of the `Tech` to register.\n   *\n   * @param {Object} tech\n   *        The `Tech` class to register.\n   */\n  static registerTech(name, tech) {\n    if (!Tech.techs_) {\n      Tech.techs_ = {};\n    }\n\n    if (!Tech.isTech(tech)) {\n      throw new Error(`Tech ${name} must be a Tech`);\n    }\n\n    if (!Tech.canPlayType) {\n      throw new Error('Techs must have a static canPlayType method on them');\n    }\n    if (!Tech.canPlaySource) {\n      throw new Error('Techs must have a static canPlaySource method on them');\n    }\n\n    name = toTitleCase(name);\n\n    Tech.techs_[name] = tech;\n    Tech.techs_[toLowerCase(name)] = tech;\n    if (name !== 'Tech') {\n      // camel case the techName for use in techOrder\n      Tech.defaultTechOrder_.push(name);\n    }\n    return tech;","sourceCodeStart":1000,"sourceCodeEnd":1036,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/tech/tech.js#L1000-L1036","documentation":"Thrown by Tech.registerTech(name, tech) when Tech.isTech(tech) returns false. isTech accepts a class whose prototype chain includes Tech, a Tech instance, or the Tech class itself. The guard prevents registering an arbitrary object/function as a playback tech, which would break tech resolution in the player.","triggerScenarios":"Calling videojs.registerTech('MyTech', PlainFunction) where PlainFunction does not extend Tech; passing a plain options object instead of a class; passing a source-handler module or a plugin constructor by mistake.","commonSituations":"Writing a custom playback tech and forgetting to extend the base Tech class; copying a plugin-style definition into registerTech; bundler/tree-shaking or transpilation that breaks the ES6 extends prototype chain (e.g. Babel loose mode without the inherits helper).","solutions":["Make your tech class extend Tech: import { Tech } from 'video.js'; class MyTech extends Tech { ... }","Register the class (not an instance) unless isTech also matches instances of a Tech subclass.","Confirm the transpiled output preserves the prototype chain (check MyTech.prototype instanceof videojs.getTech('Tech'))."],"exampleFix":"// before\nclass FlashLike {}\nvideojs.registerTech('FlashLike', FlashLike);\n// after\nimport { Tech } from 'video.js';\nclass FlashLike extends Tech {}\nvideojs.registerTech('FlashLike', FlashLike);","handlingStrategy":"type-guard","validationCode":"function registerTechSafe(name, tech) {\n  const Tech = videojs.getTech('Tech');\n  if (!Tech.isTech(tech)) {\n    throw new TypeError(`${name} must be a class extending Tech`);\n  }\n  videojs.registerTech(name, tech);\n}","typeGuard":"function isTechClass(tech) {\n  const Tech = videojs.getTech('Tech');\n  return Tech.isTech(tech);\n}","tryCatchPattern":"try {\n  videojs.registerTech(name, tech);\n} catch (err) {\n  if (/must be a Tech/.test(err.message)) {\n    console.error(`${name} does not extend videojs.Tech; registration skipped.`);\n  } else { throw err; }\n}","preventionTips":["Always extend videojs.Tech when authoring a custom tech.","Call videojs.Tech.isTech(MyTech) in your test suite before registerTech.","Register the class, not an instance, unless isTech matches instances."],"tags":["tech","registration","prototype-chain","api-misuse"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}