Skip to content

Error taxonomy

import { Aside } from ‘@astrojs/starlight/components’;

The library throws structured errors. Every library-originated throw is a GameboardError subclass — consumers can branch on instanceof without regex’ing messages.

import {
GameboardError, // base — catch this to handle ANY library error
GameboardValidationError, // input data failed structural validation
GameboardManifestError, // manifest is malformed / version-incompatible
GameboardScenarioError, // scenario JSON / blueprint / recipe failed to compile or load
GameboardRuntimeError, // runtime hit unrecoverable state
GameboardCliError, // CLI got invalid flags / illegal output paths
GameboardIoError, // ingest / bootstrap / filesystem couldn't proceed
} from 'declarative-hex-worlds/errors';

Or import from the umbrella:

import { GameboardValidationError } from 'declarative-hex-worlds';
Source domainSubclassExamples
src/rules/** (plan + scenario validation)GameboardValidationErrorrule conflict, blocked tile, invalid placement
src/manifest/** shape errorsGameboardManifestErrorunknown asset category, invalid export identifier
src/ingest/** filesystemGameboardIoErrormissing GLTF source directory
src/cli/commands/bootstrap/**GameboardIoErrorarchive-zip download failure, zip extract failure
src/scenario/** (recipe / blueprint / catalog)GameboardScenarioErrorscenario did not compile, recipe missing tiles
src/gameboard/**, src/coordinates/**, src/simulation/**, src/koota/**, src/systems/**, src/movement/**, src/patrol/**, src/quests/**, src/actors/**, src/pieces/**, src/interop/**, src/commands/**, src/selectors/**, src/three/**, src/react/**GameboardRuntimeErrorunknown entity, broken trait shape, missing tile at coordinates
src/cli/cli.tsGameboardCliErrormissing required flag, illegal path

Catch a specific category:

import { GameboardValidationError, validateGameboardScenario } from 'declarative-hex-worlds';
try {
const scenario = validateGameboardScenario(input);
} catch (e) {
if (e instanceof GameboardValidationError) {
console.error('Scenario invalid:', e.message);
showUserError(e.message);
return;
}
throw e; // re-throw anything unexpected
}

Catch any library error (separate from genuine bugs like TypeError, ReferenceError):

import { GameboardError } from 'declarative-hex-worlds';
try {
await loadAndRun(input);
} catch (e) {
if (e instanceof GameboardError) {
// library-originated — show a UI error
showError(`Library error: ${e.message}`);
return;
}
// genuine bug — let it propagate to the global handler
throw e;
}

Walk the cause chain (when cause is set):

try {
await bootstrapKayKitAssets(options);
} catch (e) {
if (e instanceof GameboardError && e.cause instanceof Error) {
console.error('Cause:', e.cause.message);
}
throw e;
}

Every subclass takes (message, options?):

class GameboardError extends Error {
constructor(message: string, options?: { cause?: unknown });
}

Subclasses set .name to their class name automatically (new.target.name), so error logs read GameboardValidationError: ... not Error: ....

PRD D2 preserved every existing error message verbatim during the migration. Consumers that grep messages today keep working. Don’t change a message lightly; treat it as part of the API contract.

  • TypeError / ReferenceError / RangeError — these are bugs in the library or in your usage. Report them.
  • Errors thrown from npm dependencies (tar, seedrandom, etc.) — these propagate unwrapped.
  • Browser-side errors from three.js / WebGL — these are rendering issues, not library logic errors.