mrdoob/three.js · error · Error

setTitle: Unknown script

Error message

setTitle: Unknown script

What it means

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.

Source

Thrown at editor/js/Script.js:417

				case 'vertexShader':

					title.setValue( object.material.name + ' / ' + strings.getKey( 'script/title/vertexShader' ) );
					break;

				case 'fragmentShader':

					title.setValue( object.material.name + ' / ' + strings.getKey( 'script/title/fragmentShader' ) );
					break;

				case 'programInfo':

					title.setValue( object.material.name + ' / ' + strings.getKey( 'script/title/programInfo' ) );
					break;

				default:

					throw new Error( 'setTitle: Unknown script' );

			}

		}

	}

	signals.editScript.add( function ( object, script ) {

		let mode, source;

		if ( typeof ( script ) === 'object' ) {

			mode = 'javascript';
			source = script.source;

		} else {

View on GitHub (pinned to da05705fa3)

Solutions

  1. 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.
  2. 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.
  3. If you are calling the editor programmatically, pass a script object ({name, source}) for JavaScript editing rather than an ad-hoc string.

Example fix

// before
signals.editScript.dispatch( object, 'fragShader' );

// after — use the exact key the switches recognize
signals.editScript.dispatch( object, 'fragmentShader' );

// or, when adding support for a new stage, extend BOTH switches:
// setTitle switch:
case 'computeShader':
  title.setValue( object.material.name + ' / compute' );
  break;
// editScript switch:
case 'computeShader':
  mode = 'glsl';
  source = object.material.computeShader || '';
  break;
Defensive patterns

Strategy: validation

Validate before calling

// Whitelist the script keys the editor recognizes before dispatching.
const SCRIPT_KEYS = new Set( [ 'vertexShader', 'fragmentShader', 'programInfo' ] );
function dispatchEditScript( object, script ) {
  if ( typeof script === 'string' && ! SCRIPT_KEYS.has( script ) ) {
    throw new TypeError( `Unsupported editScript key: ${script}` );
  }
  signals.editScript.dispatch( object, script );
}

Type guard

// Distinguish a script object from a recognized shader/program string key.
function isKnownScriptKey( v ) {
  return typeof v === 'string' &&
    ( v === 'vertexShader' || v === 'fragmentShader' || v === 'programInfo' );
}
function isScriptObject( v ) {
  return v !== null && typeof v === 'object' && typeof v.source === 'string';
}
function isEditableScript( v ) {
  return isScriptObject( v ) || isKnownScriptKey( v );
}

Try / catch

// Wrap custom editor wiring so an unknown key degrades gracefully.
try {
  signals.editScript.dispatch( object, script );
} catch ( err ) {
  if ( /setTitle: Unknown script|editScript: Unknown script/.test( err.message ) ) {
    console.error( 'editScript rejected key; falling back to programInfo', script );
    signals.editScript.dispatch( object, 'programInfo' );
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12). Data as JSON: /api/errors/2da8e6828b7c1609. Report an issue: GitHub.