{"record":{"id":"2da8e6828b7c1609","repo":"mrdoob/three.js","slug":"settitle-unknown-script","errorCode":null,"errorMessage":"setTitle: Unknown script","messagePattern":"setTitle: Unknown script","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"editor/js/Script.js","lineNumber":417,"sourceCode":"\n\t\t\t\tcase 'vertexShader':\n\n\t\t\t\t\ttitle.setValue( object.material.name + ' / ' + strings.getKey( 'script/title/vertexShader' ) );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'fragmentShader':\n\n\t\t\t\t\ttitle.setValue( object.material.name + ' / ' + strings.getKey( 'script/title/fragmentShader' ) );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'programInfo':\n\n\t\t\t\t\ttitle.setValue( object.material.name + ' / ' + strings.getKey( 'script/title/programInfo' ) );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\n\t\t\t\t\tthrow new Error( 'setTitle: Unknown script' );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tsignals.editScript.add( function ( object, script ) {\n\n\t\tlet mode, source;\n\n\t\tif ( typeof ( script ) === 'object' ) {\n\n\t\t\tmode = 'javascript';\n\t\t\tsource = script.source;\n\n\t\t} else {\n","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/mrdoob/three.js/blob/da05705fa31f02710c19772a2aa70c7454807f0c/editor/js/Script.js#L399-L435","documentation":"Thrown by the three.js editor's Script panel setTitle() when it receives a script argument that is neither a script object nor one of the three recognized shader/program string keys ('vertexShader', 'fragmentShader', 'programInfo'). The switch in setTitle() has no case for any other string, so the default branch aborts. It is a defensive guard that mirrors the one in the editScript handler (error [1]); setTitle is called from that handler at Script.js:472, so this fires only if the upstream switch did not already throw on the same value.","triggerScenarios":"Dispatching signals.editScript with a string value other than 'vertexShader', 'fragmentShader', or 'programInfo' (e.g. a typo like 'fragShader', or a newly introduced shader stage such as 'computeShader'). In the shipping editor the only dispatchers are Sidebar.Material.Program.js (which sends exactly those three literals) and Sidebar.Script.js (which sends a script object), so this is reached only by a custom/modified dispatch site.","commonSituations":"Extending the editor to edit additional shader stages or new script kinds without adding the matching case to both switches. Third-party editor plugins that call signals.editScript.dispatch() directly with an unsupported string. Refactors that rename a key in one place but not the other (the two switches must stay in sync).","solutions":["If you added a new editable script kind, add a case for it in BOTH the setTitle switch (Script.js:398) and the editScript switch (Script.js:436), using the same string literal.","If the value is unexpected, locate the dispatching code (grep for signals.editScript.dispatch) and correct the string to one of 'vertexShader' | 'fragmentShader' | 'programInfo', or pass a script object for a JS edit.","If you are calling the editor programmatically, pass a script object ({name, source}) for JavaScript editing rather than an ad-hoc string."],"exampleFix":"// before\nsignals.editScript.dispatch( object, 'fragShader' );\n\n// after — use the exact key the switches recognize\nsignals.editScript.dispatch( object, 'fragmentShader' );\n\n// or, when adding support for a new stage, extend BOTH switches:\n// setTitle switch:\ncase 'computeShader':\n  title.setValue( object.material.name + ' / compute' );\n  break;\n// editScript switch:\ncase 'computeShader':\n  mode = 'glsl';\n  source = object.material.computeShader || '';\n  break;","handlingStrategy":"validation","validationCode":"// Whitelist the script keys the editor recognizes before dispatching.\nconst SCRIPT_KEYS = new Set( [ 'vertexShader', 'fragmentShader', 'programInfo' ] );\nfunction dispatchEditScript( object, script ) {\n  if ( typeof script === 'string' && ! SCRIPT_KEYS.has( script ) ) {\n    throw new TypeError( `Unsupported editScript key: ${script}` );\n  }\n  signals.editScript.dispatch( object, script );\n}","typeGuard":"// Distinguish a script object from a recognized shader/program string key.\nfunction isKnownScriptKey( v ) {\n  return typeof v === 'string' &&\n    ( v === 'vertexShader' || v === 'fragmentShader' || v === 'programInfo' );\n}\nfunction isScriptObject( v ) {\n  return v !== null && typeof v === 'object' && typeof v.source === 'string';\n}\nfunction isEditableScript( v ) {\n  return isScriptObject( v ) || isKnownScriptKey( v );\n}","tryCatchPattern":"// Wrap custom editor wiring so an unknown key degrades gracefully.\ntry {\n  signals.editScript.dispatch( object, script );\n} catch ( err ) {\n  if ( /setTitle: Unknown script|editScript: Unknown script/.test( err.message ) ) {\n    console.error( 'editScript rejected key; falling back to programInfo', script );\n    signals.editScript.dispatch( object, 'programInfo' );\n  } else throw err;\n}","preventionTips":["Keep the two switches (editScript at Script.js:436 and setTitle at Script.js:398) in sync whenever you add a script kind.","Centralize the list of valid string keys in one constant and drive both switches from it.","Prefer dispatching a script object for JS edits and the exact literals for shader edits."],"tags":["editor","script","shader","switch-enum"],"backgroundTag":null,"analyzedSha":"da05705fa31f02710c19772a2aa70c7454807f0c","analyzedAt":"2026-08-12T22:51:37.160Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}