{"record":{"id":"62da8933cffa0624","repo":"videojs/video.js","slug":"no-techorder-specified-did-you-overwrite-videojs","errorCode":null,"errorMessage":"No techOrder specified. Did you overwrite videojs.options instead of just changing the properties you want to override?","messagePattern":"No techOrder specified\\. Did you overwrite videojs\\.options instead of just changing the properties you want to override\\?","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/js/player.js","lineNumber":423,"sourceCode":"    // Init state audioOnlyMode_\n    this.audioOnlyMode_ = false;\n\n    // Init state audioPosterMode_\n    this.audioPosterMode_ = false;\n\n    // Init state audioOnlyCache_\n    this.audioOnlyCache_ = {\n      controlBarHeight: null,\n      playerHeight: null,\n      hiddenChildren: []\n    };\n\n    // if the global option object was accidentally blown away by\n    // someone, bail early with an informative error\n    if (!this.options_ ||\n        !this.options_.techOrder ||\n        !this.options_.techOrder.length) {\n      throw new Error('No techOrder specified. Did you overwrite ' +\n                      'videojs.options instead of just changing the ' +\n                      'properties you want to override?');\n    }\n\n    // Store the original tag used to set options\n    this.tag = tag;\n\n    // Store the tag attributes used to restore html5 element\n    this.tagAttributes = tag && Dom.getAttributes(tag);\n\n    // Update current language\n    this.language(this.options_.language);\n\n    // Update Supported Languages\n    if (options.languages) {\n      // Normalise player option languages to lowercase\n      const languagesToLower = {};\n","sourceCodeStart":405,"sourceCodeEnd":441,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/player.js#L405-L441","documentation":"On player construction video.js reads this.options_.techOrder (the list of playback technologies to try, e.g. ['html5','flash']). If options_ itself, techOrder, or its length is missing, the global videojs.options was almost certainly overwritten instead of merged, which would make playback impossible. The error message points at the most common cause directly.","triggerScenarios":"Doing videojs.options = {controls: true} (replacing the object) instead of videojs.options.controls = true; passing {techOrder: undefined} explicitly; a plugin that assigns over videojs.options.","commonSituations":"Tutorial code that reassigns videojs.options; SSR or build setups that mutate the global; integrating video.js with a config layer that wholesale replaces rather than merges.","solutions":["Mutate individual properties: videojs.options.controls = true; videojs.options.techOrder = ['html5'];","Merge instead of replace: Object.assign(videojs.options, myConfig) or videojs.options = {...videojs.options, ...myConfig}.","Pass options per-instance: videojs('vid', {techOrder: ['html5'], ...})."],"exampleFix":"// before\nvideojs.options = { controls: true }; // wipes techOrder\n// after\nvideojs.options.controls = true;\n// or merge\nvideojs.options = { ...videojs.options, controls: true };","handlingStrategy":"validation","validationCode":"function mergeVideojsOptions(patch) {\n  if (!videojs.options.techOrder) {\n    throw new Error('refusing to apply patch: techOrder missing');\n  }\n  Object.assign(videojs.options, patch);\n}","typeGuard":"const hasTechOrder = (o) =>\n  o && Array.isArray(o.techOrder) && o.techOrder.length > 0;","tryCatchPattern":null,"preventionTips":["Never reassign videojs.options; mutate or merge it.","Pass techOrder per-instance in videojs('id', {techOrder: [...]}).","Add a smoke-test asserting videojs.options.techOrder length."],"tags":["player","config","tech","videojs"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}