[Canonical page](<https://docs.dhtmlx.com/planning-engine/wasm/how-to/reschedule-a-branch/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Reschedule a branch

Reschedule one task and the work that depends on it, and leave the rest of the project where it is.

The scope starts at the task you name. It takes in that task's summary ancestors and descendants, then every task that follows it through links, together with their own ancestors and descendants. With `inclusive: true` (the default), the scope also reaches back through links to the tasks that lead into it. Tasks outside the scope keep their dates, but they still push the tasks inside it.

## Steps

1. Serialize the [solve options](<https://docs.dhtmlx.com/planning-engine/wasm/api/types/solve-options.md>) with a [`subtree`](<https://docs.dhtmlx.com/planning-engine/wasm/api/types/common.md#subtree>) that names the task the branch starts from. `inclusive` defaults to `true`:

   ```js
   const options = JSON.stringify({ subtree: { task: "design" } });
   ```

   To keep the predecessors of `design` where they are and reschedule only `design` and the work after it, set `inclusive: false`:

   ```js
   const options = JSON.stringify({ subtree: { task: "design", inclusive: false } });
   ```

2. Pass the options to [`solve`](<https://docs.dhtmlx.com/planning-engine/wasm/api/project-solve.md>). Send the data string on the first load, or `undefined` to reschedule the current state. For a one-shot job without a handle, [`schedule`](<https://docs.dhtmlx.com/planning-engine/wasm/api/schedule.md>) takes the same options:

   ```js
   const response = JSON.parse(project.solve(undefined, options));
   ```

3. Check `ok`, then write the entries of [`result.updates`](<https://docs.dhtmlx.com/planning-engine/wasm/api/types/schedule-result.md#updates>) back to your model. Each entry is a task in the scope that moved. After a `solve`, the scoped dates become the accepted baseline.

The full example below has two independent chains, `backend → api` and `design → ui`. Both successors start too early. The scoped solve fixes only the `design` branch:

```js
const { JsonProject } = require("./pkg-node/plen_wasm.js");

function unwrap(text) {
  const response = JSON.parse(text);
  if (!response.ok) {
    const { kind, code, message, path } = response.error;
    throw new Error(`${kind} ${code ?? ""}: ${message} (at ${path})`);
  }
  return response.result;
}

const data = {
  // 24/7 time keeps the example dates easy to check.
  config: { use_calendars: false },
  tasks: [
    { id: "backend", start_date: "2026-01-01 00:00", duration: 2 },
    { id: "api", start_date: "2026-01-01 00:00", duration: 1 },
    { id: "design", start_date: "2026-01-01 00:00", duration: 3 },
    { id: "ui", start_date: "2026-01-01 00:00", duration: 1 },
  ],
  links: [
    { id: "l1", source: "backend", target: "api", type: "fs" },
    { id: "l2", source: "design", target: "ui", type: "fs" },
  ],
};

const options = JSON.stringify({ subtree: { task: "design" } });

const project = new JsonProject("{}");
try {
  const result = unwrap(project.solve(JSON.stringify(data), options));
  for (const u of result.updates) {
    console.log(`${u.id} ${u.start_date}..${u.end_date}`);
  }
} finally {
  project.free();
}
```

## Preview a branch

To see what rescheduling a branch would do without changing the project, set the same [`subtree`](<https://docs.dhtmlx.com/planning-engine/wasm/api/types/common.md#subtree>) in the options of [`preview`](<https://docs.dhtmlx.com/planning-engine/wasm/api/project-preview.md>):

```js
const preview = unwrap(
  project.preview("{}", JSON.stringify({ subtree: { task: "backend" } })),
);
```

The preview scope applies to that call only. It doesn't touch the baseline or the cached solve result. A preview scope can also name a task that the same [change set](<https://docs.dhtmlx.com/planning-engine/wasm/api/types/scheduling-changes.md>) adds.

## Things to know

- Tasks outside the scope don't move until you solve them. In the example, the next `project.solve(undefined, "{}")` moves only `api`, because `ui` is already accepted.
- The result cache uses the whole options object as its key. A different [`subtree`](<https://docs.dhtmlx.com/planning-engine/wasm/api/types/common.md#subtree>) replans from the accepted dates. The same `subtree` again returns the cached result.
- With [`config.gap_behavior: "compress"`](<https://docs.dhtmlx.com/planning-engine/wasm/api/types/common.md#gap-behavior>) and [`config.apply_constraints: false`](<https://docs.dhtmlx.com/planning-engine/wasm/api/types/scheduling-config.md>), the task you name never moves earlier than its current dates. With `inclusive: true`, its predecessors in the scope keep that floor too.
- With [`includeUnchanged`](<https://docs.dhtmlx.com/planning-engine/wasm/how-to/load-all-task-dates.md>), a scoped solve reports every task in the scope, plus the out-of-scope tasks a sparse scoped solve would report.
- On a project with a dependency cycle, nothing is scheduled, scoped or not. Check [`result.cycles`](<https://docs.dhtmlx.com/planning-engine/wasm/api/types/schedule-result.md#cycle>).
- An unknown or unscheduled task in `subtree.task` returns a `validation` error at path `subtree.task`, with the message `unknown or unscheduled scope task`. The project keeps its previous state and cached result. See [Error handling](<https://docs.dhtmlx.com/planning-engine/wasm/error-handling.md>).

## Result

Run the example with `node`. It prints one line. Only `ui` moves, to start after `design` ends. `api` still overlaps `backend`:

```text
ui 2026-01-04 00:00..2026-01-05 00:00
```

Without `subtree`, the same solve also moves `api` to `2026-01-03 00:00`.
