[Canonical page](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/input-error/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# InputError

The data or options passed to a call are invalid. It reaches the caller as [`Error::Input`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/error.md>); match on that variant to read the kind, message and field path.

## Declaration

```rust
#[derive(Debug)]
pub struct InputError {
    pub kind: InputErrorKind,
    pub message: String,
    pub path: Option<String>,
}

impl std::error::Error for InputError {}
impl std::fmt::Display for InputError {} // writes `message`
```

## Fields

| Field | Type | Description |
|---|---|---|
| `kind` | [`InputErrorKind`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/input-error-kind.md>) | `Parse` or `Validation`. Calls on the native API report `Validation`. |
| `message` | `String` | Human-readable reason. `Display` prints this text and nothing else. |
| `path` | `Option<String>` | Path to the offending field in the input, such as `tasks[3].constraint_date` or `scope.resources`. `None` when the error isn't tied to a single field. |

The `path` is relative to the argument the call received: `tasks[i]...` for a [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>), `slots[i]...` for the slots passed to [`suggest_assignments`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#suggest_assignments>), `scope.resources` for leveling options.

## Associated functions

### validation

```rust
pub fn validation(path: impl Into<String>, message: impl Into<String>) -> InputError
```

Builds an error with `kind:` [`InputErrorKind::Validation`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/input-error-kind.md>) and `path: Some(path)`.

| Name | Type | Description |
|---|---|---|
| `path` | `impl Into<String>` | Path to the invalid field |
| `message` | `impl Into<String>` | Reason shown to the user |

**Returns** the new `InputError`. Wrap it with `.into()` to get an [`Error`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/error.md>).

## Returned by

These calls return `Err(Error::Input(_))` when validation fails. The page of each call lists the checks it runs.

| Call | Fails on |
|---|---|
| [`Project::solve`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#solve>) | invalid replacement `data` |
| [`schedule`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/schedule.md>), [`schedule_state`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/schedule-state.md>) | invalid `data` |
| [`Project::analyze`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#analyze>) | invalid supplied `data` |
| [`Project::preview`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#preview>) | the first rejected operation in `changes`; an invalid `profile` query |
| [`Project::level`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#level>) | unknown id in `scope`; a backward-scheduled project |
| [`Project::load_profile`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#load_profile>) | invalid range; unknown resource |
| [`Project::evaluate`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#evaluate>), [`Project::evaluate_with`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#evaluate_with>) | unknown focus id; invalid `level` options |
| [`Project::suggest_assignments`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#suggest_assignments>) | invalid options or slots |

[`MatchError::Invalid`](<https://docs.dhtmlx.com/planning-engine/rust/api/assign/match-error.md>) from `plen_assign` converts into an `InputError` of kind `Validation` with the same path and message when it passes through `?` into an [`Error`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/error.md>).

## Serialization

With the `serde` feature, `InputError` implements `Serialize` and `Deserialize`. Field names are camelCase, `kind` is `"parse"` or `"validation"`, and `path` is omitted when it's `None`.

## Example

```rust
use plen_core::{schedule, Error, ProjectData, SolveOptions, TaskData};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // A leaf task with no start, end or duration fails strict validation.
    let data = ProjectData {
        tasks: vec![TaskData::new(1)],
        ..Default::default()
    };

    match schedule(data, &SolveOptions::default()) {
        Ok(result) => println!("{} tasks moved", result.updates.len()),
        Err(Error::Input(e)) => {
            let at = e.path.as_deref().unwrap_or("<input>");
            eprintln!("invalid input at {at}: {}", e.message);
        }
        Err(e) => return Err(e.into()),
    }
    Ok(())
}
```

For recovery patterns, see [Error handling](<https://docs.dhtmlx.com/planning-engine/rust/error-handling.md>).

## Related

- [`Error`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/error.md>) - wraps this type in `Error::Input`
- [`InputErrorKind`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/input-error-kind.md>) - the type of `kind`
- [`Validation`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/validation.md>) - selects repair instead of this error for invalid data
- [Accept messy input](<https://docs.dhtmlx.com/planning-engine/rust/how-to/accept-messy-input.md>) - shows how to load data that would fail validation
