Errors#

Every Project method and schedule is synchronous and reports failure by throwing. The package exports two error classes, InputError and ProjectError; both extend Error and can be checked with instanceof. Conflicts, dependency cycles, non-convergence and rejected apply operations are not errors: they're reported inside the result.

InputError#

Thrown when the data or options passed to a call are invalid. The project keeps its previous state.

class InputError extends Error {
  name: "InputError";
  kind: "parse" | "validation";
  message: string;
  path: string | null;
}
Field Type Description
name string Always "InputError".
kind "parse" | "validation" "parse": the input doesn't have the expected shape (wrong type, unknown key in options or a change set). "validation": the shape is right, but a value isn't allowed.
message string Short description of the problem, such as "invalid duration".
path string | null Location of the offending field, such as "tasks[0].start_date" or "pool.workers[1].resource". null when the error has no single field.

InputError is also thrown while the input objects are read, before decoding:

message When
"Numbers must be finite" A number is NaN or ±Infinity. path is the property name only, or null.
"Invalid Date" A Date in the input is invalid. path is null.
"Unknown dates representation" new Project({ dates }) got a value other than "string" or "date". path is "dates".

Thrown by: new Project, schedule, Project#solve, Project#preview, Project#analyze, Project#apply, Project#level, Project#loadProfile, Project#evaluate, Project#slots, Project#suggestAssignments. Each operation page lists the inputs it rejects.

Note

new Project(options) throws an InputError if an option is unknown or has an invalid value.

Note

slots throws InputError / ProjectError like the other Project methods.

ProjectError#

Thrown when a call doesn't fit the project's current state. The input may be valid; the project keeps its state.

class ProjectError extends Error {
  name: "ProjectError";
  code: "no-baseline" | "stale-baseline" | "needs-resync";
  message: string;
}
Field Type Description
name string Always "ProjectError".
code "no-baseline" | "stale-baseline" | "needs-resync" Reason for the error; values below.
message string Same string as code.
code When it occurs Thrown by
"no-baseline" The project has no solved baseline: it was never solved, or apply ran after the last solve. preview, loadProfile, evaluate, slots, suggestAssignments
"stale-baseline" A baselineId in the options or in SchedulingChanges isn't the current baseline. preview, apply, loadProfile, evaluate, suggestAssignments
"needs-resync" An earlier apply rejected an operation, and no full solve(data) has run since. apply, solve(null), level

For how to recover from each code, see Error handling.

Other errors#

These are not exported classes. Check them by name, message or constructor.

Error When it occurs
Error("Project has been disposed") Any call on a project after its dispose().
TypeError The input has a circular reference or a BigInt. The messages match JSON.stringify.
Error with name "Panic" An internal engine assertion failed. This is a library bug.
Note

dispose() is optional; after it, every call on that project throws Error("Project has been disposed").

Example#

import { InputError, ProjectError, schedule } from "plen-js";

try {
  schedule({ tasks: [{ id: 1, start_date: "2026-01-05 08:00", duration: -1 }] });
} catch (error) {
  if (error instanceof InputError) {
    console.error(error.kind, error.path, error.message);
  } else if (error instanceof ProjectError) {
    console.error(error.code);
  } else {
    throw error;
  }
}