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


# AnalyticsStatus

Tells you whether the engine could compute the analytics you requested. It's the type of the [`Analytics::status`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/analytics.md>) field, which you get in [`ScheduleResult::analytics`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/schedule-result.md#analytics>) when [`AnalyticsOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/analytics-options.md>) asks for the critical path or slack.

## Declaration

```rust
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AnalyticsStatus {
    Available,
    Invalid,
}
```

With the `serde` feature, `AnalyticsStatus` implements `Serialize` and `Deserialize`. Variants are written in kebab-case: `"available"`, `"invalid"`.

## Variants

| Variant | Serialized | Description |
|---|---|---|
| `Available` | `"available"` | The analytics were computed. [`Analytics::critical_path`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/analytics.md>) and `Analytics::slack` hold whatever you requested. |
| `Invalid` | `"invalid"` | The task graph has a dependency cycle, so the analytics can't be computed. `critical_path` and `slack` are both `None`. |

When the status is `Invalid`, look in [`ScheduleResult::cycles`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/schedule-result.md#cycles>) to find the cycle.

## Example

Request the critical path for two tasks linked in a cycle, then check the status before reading it:

```rust
use plen_core::{
    schedule, AnalyticsOptions, AnalyticsStatus, DateTime, LinkData, LinkType, ProjectData,
    SolveOptions, TaskData,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let start = DateTime::from_ymd_hm(2026, 1, 5, 8, 0).ok_or("invalid date")?;
    let mut a = TaskData::new("a");
    a.start_date = Some(start);
    a.duration = Some(1.0);
    let mut b = TaskData::new("b");
    b.start_date = Some(start);
    b.duration = Some(1.0);

    // a -> b -> a: a dependency cycle.
    let link = |id: &str, source: &str, target: &str| LinkData {
        id: id.into(),
        source: source.into(),
        target: target.into(),
        link_type: LinkType::Fs,
        lag: 0.0,
        lag_unit: None,
    };
    let data = ProjectData {
        tasks: vec![a, b],
        links: vec![link("l1", "a", "b"), link("l2", "b", "a")],
        ..Default::default()
    };

    let options = SolveOptions {
        analytics: AnalyticsOptions { critical_path: true, ..Default::default() },
        ..Default::default()
    };
    let result = schedule(data, &options)?;

    if let Some(analytics) = &result.analytics {
        match analytics.status {
            AnalyticsStatus::Available => {
                if let Some(critical) = &analytics.critical_path {
                    println!("critical tasks: {:?}", critical.tasks);
                }
            }
            AnalyticsStatus::Invalid => {
                println!("no analytics: {} cycle(s) in the graph", result.cycles.len());
            }
        }
    }
    Ok(())
}
```

## Related

- [`Analytics`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/analytics.md>) - holds the status next to the computed data
- [`Cycle`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/cycle.md>) - the cycle that makes the status `Invalid`
- [`AnalyticsOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/analytics-options.md>) - requests the analytics the status reports on
- [Critical path and slack](<https://docs.dhtmlx.com/planning-engine/rust/scheduling/critical-path-and-slack.md#reading-the-result>) - checks the status before reading analytics
