libnyanpasu/clash-nyanpasu · error

runtime snapshot node does not exist

Error message

runtime snapshot node does not exist

What it means

Thrown by `RuntimeSnapshot::inspection_content` when `node_id` is out of bounds for the current snapshot's config graph (`graph.nodes.get(node_id as usize)` returned None). Node ids are indices into the snapshot graph built during the config pipeline; a valid id in one snapshot may be invalid in another. The library treats this as a caller contract violation rather than silently returning empty content.

Source

Thrown at backend/tauri/src/client/runtime_inspection.rs:94

                .collect(),
        }
    }

    fn inspection_content(
        &self,
        snapshot_id: &str,
        node_id: u32,
    ) -> anyhow::Result<RuntimeInspectionContent> {
        anyhow::ensure!(
            self.inspection_id == snapshot_id,
            "runtime snapshot changed; refresh the inspection"
        );
        let node = self
            .inspection
            .graph
            .nodes
            .get(node_id as usize)
            .ok_or_else(|| anyhow::anyhow!("runtime snapshot node does not exist"))?;
        let yaml = serde_yaml::to_string(&node.snapshot.config)?;
        Ok(RuntimeInspectionContent {
            diff: self
                .inspection
                .graph
                .comparison_parent(node_id)
                .map(|parent_id| -> anyhow::Result<_> {
                    Ok(RuntimeInspectionDiff {
                        parent_id,
                        hunks: self.inspection.graph.nodes[parent_id as usize]
                            .snapshot
                            .diff_yaml_to(&yaml)?,
                    })
                })
                .transpose()?,
            yaml,
            logs: self
                .inspection

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Always obtain node ids from the current `inspect_runtime()` summary's `nodes` array, never from cached data.
  2. Re-fetch the inspection summary whenever the snapshot changes, then map UI selections to fresh ids.
  3. Handle the error by reloading the whole inspection view (summary + node) instead of retrying the same id.
  4. Validate `node_id < summary.nodes.len()` client-side before calling.

Example fix

// before
client.inspect_runtime_node(&summary.snapshot_id, old_node_id).await?;
// after
if let Some(node) = summary.nodes.get(old_node_id as usize) {
    client.inspect_runtime_node(&summary.snapshot_id, node.id).await?;
} else {
    // refresh summary and re-resolve the node
}
Defensive patterns

Strategy: validation

Validate before calling

if node_id as usize >= summary.nodes.len() {
    anyhow::bail!("node {node_id} not in current inspection ({} nodes)", summary.nodes.len());
}

Type guard

fn resolve_node<'a>(summary: &'a RuntimeInspection, node_id: u32) -> Option<&'a RuntimeInspectionNode> {
    summary.nodes.get(node_id as usize)
}

Try / catch

match client.inspect_runtime_node(&snapshot_id, node_id).await {
    Ok(content) => content,
    Err(e) if e.to_string().contains("node does not exist") => {
        // reload summary and re-resolve the node id
        let summary = client.inspect_runtime().await.ok_or_else(|| anyhow!("no inspection"))?;
        client.inspect_runtime_node(&summary.snapshot_id, summary.root_id).await?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `inspect_runtime_node` (via `NyanpasuClient`) with a node_id larger than or equal to `nodes.len()` of the promoted snapshot's graph — typically an id from a previous inspection summary, a hardcoded id, or an id from a different snapshot whose graph has fewer nodes.

Common situations: Frontend caches node ids from an old inspection tree; UI navigates to a node that no longer exists after the pipeline shape changed (profiles added/removed change the graph); off-by-one or index confusion between tree position and node id.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/aac60bec07adb6fb. Report an issue: GitHub.