{"record":{"id":"168f3600c9f0db6b","repo":"videojs/video.js","slug":"a-tech-was-not-provided","errorCode":null,"errorMessage":"A tech was not provided.","messagePattern":"A tech was not provided\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/js/tracks/text-track.js","lineNumber":164,"sourceCode":"   * @param {string} [options.label='']\n   *        The menu label for this track.\n   *\n   * @param {string} [options.language='']\n   *        A valid two character language code.\n   *\n   * @param {string} [options.srclang='']\n   *        A valid two character language code. An alternative, but deprioritized\n   *        version of `options.language`\n   *\n   * @param {string} [options.src]\n   *        A url to TextTrack cues.\n   *\n   * @param {boolean} [options.default]\n   *        If this track should default to on or off.\n   */\n  constructor(options = {}) {\n    if (!options.tech) {\n      throw new Error('A tech was not provided.');\n    }\n\n    const settings = merge(options, {\n      kind: TextTrackKind[options.kind] || 'subtitles',\n      language: options.language || options.srclang || ''\n    });\n    let mode = TextTrackMode[settings.mode] || 'disabled';\n    const default_ = settings.default;\n\n    if (settings.kind === 'metadata' || settings.kind === 'chapters') {\n      mode = 'hidden';\n    }\n    super(settings);\n\n    this.tech_ = settings.tech;\n\n    this.cues_ = [];\n    this.activeCues_ = [];","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/tracks/text-track.js#L146-L182","documentation":"Thrown by the TextTrack constructor when options.tech is missing. A TextTrack is tightly coupled to its owning Tech for cue rendering, event dispatch, and track-list management; without a tech reference it cannot function. The constructor defaults options to {} and immediately checks the tech key.","triggerScenarios":"Constructing 'new TextTrack({ kind: \"subtitles\", label: \"en\" })' with no tech; passing an options object missing the 'tech' key; instantiating TextTrack in a custom component instead of going through the player/tech track APIs.","commonSituations":"Directly instantiating TextTrack in tests or custom components rather than using player.addTextTrack / player.addRemoteTextTrack (which inject the tech automatically); a refactor that drops the tech reference from the options object.","solutions":["Prefer player.addTextTrack() / addRemoteTextTrack(), which supply the tech automatically.","If constructing manually, pass the owning tech: new TextTrack({ ..., tech: player.tech_ }).","Ensure the options object is built from a source that always includes a tech reference."],"exampleFix":"// before\nnew TextTrack({ kind: 'subtitles', label: 'English' });\n// after\nnew TextTrack({ kind: 'subtitles', label: 'English', tech: player.tech_ });","handlingStrategy":"validation","validationCode":"function safeNewTextTrack(options) {\n  if (!options || !options.tech) {\n    throw new TypeError('TextTrack requires options.tech');\n  }\n  return new videojs.TextTrack(options);\n}","typeGuard":"function hasTechRef(options) {\n  return !!options && !!options.tech;\n}","tryCatchPattern":"try {\n  return new videojs.TextTrack(options);\n} catch (err) {\n  if (/tech was not provided/.test(err.message)) {\n    options = { ...options, tech: player.tech_ };\n    return new videojs.TextTrack(options);\n  }\n  throw err;\n}","preventionTips":["Prefer player.addTextTrack / addRemoteTextTrack, which inject the tech for you.","Never construct TextTrack directly outside of tests.","When refactoring track code, always carry the tech reference through the options object."],"tags":["text-track","tech","constructor","api-misuse"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}