[Canonical page](<https://docs.dhtmlx.com/planning-engine/java/api/errors/match-exception/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# MatchException

The exception thrown by [`SkillLayer.slots`](<https://docs.dhtmlx.com/planning-engine/java/api/skill-layer-slots.md>) and [`SkillLayer.validatePool`](<https://docs.dhtmlx.com/planning-engine/java/api/skill-layer-slots.md#skilllayervalidatepool>). It reports an invalid item in the pool or the requirements, or a project state that doesn't allow building slots. It's an unchecked `RuntimeException` but not a [`PlenException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/plen-exception.md>), so `catch (PlenException e)` doesn't catch it. [`toPlenException()`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/match-exception.md#toplenexception>) converts it to one.

## Declaration

```java
package org.dhtmlx.plen;

public abstract class MatchException extends RuntimeException {
  public MatchException(String message, RuntimeException inner)
  public MatchException(String message)

  public abstract PlenException toPlenException()

  public static class Invalid extends MatchException { ... }
  public static class Project extends MatchException { ... }
}
```

The class is abstract. Every thrown value is one of the two nested subclasses. Catch them separately, or catch `MatchException` and test with `instanceof`.

Java 21 also defines `java.lang.MatchException`. With only `import org.dhtmlx.plen.*;`, the simple name `MatchException` is ambiguous and doesn't compile. Import the class by name:

```java
import org.dhtmlx.plen.*;
import org.dhtmlx.plen.MatchException;
```

## Methods

### toPlenException

```java
public abstract PlenException toPlenException()
```

Returns the equivalent engine exception, so a method that calls both `slots` and [`Project#suggestAssignments`](<https://docs.dhtmlx.com/planning-engine/java/api/project-suggest-assignments.md>) can rethrow it and handle one exception type.

| Subclass | Returns |
|---|---|
| `Invalid` | A new [`InputException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/input-exception.md>) of kind `VALIDATION`, with the same `path` and `detail` as its message |
| `Project` | The wrapped [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/project-exception.md>) (`error`), not a copy |

## Variants

| Variant | When it occurs |
|---|---|
| [`Invalid`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/match-exception.md#invalid>) | An item of the pool or a requirement is invalid. `path` names the item, `detail` says what's wrong |
| [`Project`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/match-exception.md#project>) | The project has no accepted baseline: it's unsolved, or it has unsolved edits after [`apply`](<https://docs.dhtmlx.com/planning-engine/java/api/project-apply.md>). `code()` returns `ProjectError.NO_BASELINE` |

## Invalid

An invalid pool or requirement. Thrown by `slots` and `validatePool`; `validatePool` throws it only for `pool.workers[...]` paths.

```java
public static class Invalid extends MatchException {
  public String path;
  public String detail;

  public Invalid(String path, String message)

  public MatchException.Invalid withPath(String value)
  public MatchException.Invalid withDetail(String value)
  public PlenException toPlenException()
}
```

| Member | Type | Description |
|---|---|---|
| `path` | `String` | The invalid item, for example `requirements[2].assignments[0]` |
| `detail` | `String` | What's wrong with the item |
| `getMessage()` | `String` | `"<path>: <detail>"`, built by the constructor. Not updated by `withPath` / `withDetail` |
| `getCause()` | `Throwable` | `null` |

`path` values:

| Path | When it occurs |
|---|---|
| `pool.workers[i].resource` | Unknown resource, or the same resource listed as two workers |
| `pool.workers[i].skills[j].id` | The same skill listed twice on one worker |
| `pool.workers[i].skills[j].value` | Not finite |
| `requirements[i].id` | Duplicate requirement id, or one of its slot ids is an active assignment on another task |
| `requirements[i].task` | Unknown or unscheduled task |
| `requirements[i].count` | `0` |
| `requirements[i].units` | Not finite, or `<= 0` |
| `requirements[i].matches[j].value` | Not finite |
| `requirements[i].assignments` | More entries than `count`, or an assignment with one of this requirement's slot ids is left out of the list |
| `requirements[i].assignments[k]` | Unknown or inactive assignment, an assignment on another task, or an assignment bound twice |

## Project

The project state doesn't allow building slots. `slots` throws it with a `ProjectException` of code `NO_BASELINE`.

```java
public static class Project extends MatchException {
  public ProjectException error;

  public Project(ProjectException error)

  public MatchException.Project withError(ProjectException value)
  public ProjectError code()
  public PlenException toPlenException()
}
```

| Member | Type | Description |
|---|---|---|
| `error` | [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/project-exception.md>) | The wrapped project-state exception |
| `code()` | [`ProjectError`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/project-exception.md#projecterror>) | `error.code` |
| `getMessage()` | `String` | The message of `error`, the kebab-case code, for example `no-baseline` |
| `getCause()` | `Throwable` | `error` |

The constructor throws `NullPointerException` when `error` is `null`.

## Example

```java
import java.util.List;
import org.dhtmlx.plen.*;
import org.dhtmlx.plen.MatchException;

public class MatchExceptionExample {
  public static void main(String[] args) throws Exception {
    Project project = new Project(); // never solved

    try {
      SkillLayer.slots(project, new Pool(), List.of());
    } catch (MatchException.Project e) {
      System.out.println("project state: " + e.code()); // NO_BASELINE
    } catch (MatchException.Invalid e) {
      System.out.println(e.path + ": " + e.detail);
    }
  }
}
```

## Related

- [`SkillLayer.slots`](<https://docs.dhtmlx.com/planning-engine/java/api/skill-layer-slots.md>) - the call that throws it
- [`InputException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/input-exception.md>) - what `Invalid` converts to
- [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/project-exception.md>) - what `Project` wraps
- [Error handling](<https://docs.dhtmlx.com/planning-engine/java/error-handling.md#errors-from-skilllayerslots>) - handling slot and suggestion errors through one type
- [Skills and requirements](<https://docs.dhtmlx.com/planning-engine/java/resources-and-assignment/skills-and-requirements.md#errors>) - the checks run on pools and requirements
