Results and troubleshooting
Save a report
These examples assume PCAP points to an existing local capture and authentication is saved:
packetsafari investigate "$PCAP" --goal troubleshoot --format markdown > report.md
packetsafari investigate "$PCAP" --goal security --format json > result.json
These are separate submissions. To export another format from an existing job, resume it by ID instead of uploading again:
packetsafari investigate --job-id JOB_ID --format json > result.json
packetsafari investigate --job-id JOB_ID --format markdown > report.md
JSON contains the structured investigation result, including lifecycle, report, requested AI settings, and assessment/scan fields where applicable. Markdown renders the report and metadata in front matter. A schema-valid result may still be inconclusive; check the report and verification status.
Progress goes to stderr; the final result goes to stdout. --quiet suppresses progress but keeps results and errors:
packetsafari investigate "$PCAP" --goal security --quiet --format json > result.json
--verbose shows additional capture/job identifiers. --format ndjson is for streamed JSON events; it is not the same format as the final --format json result.
Reconnect, resume, and cancellation
The CLI follows progress and reconnects after transient observer interruptions. If it exits, retain the reported job ID and use --job-id to observe that job again. This does not start a second assessment.
Ctrl+C requests cancellation once the CLI has the job identity. During submission, the CLI attempts to obtain the receipt so it can cancel the accepted job. Read the cancellation outcome: a network failure can prevent confirmation. Check the job in the UI before assuming execution stopped. Already-uploaded captures remain available.
Common errors
| Symptom | What to check |
|---|---|
command not found | Install the CLI; put its install directory on PATH. |
missing persisted device credential from bare packetsafari | You may be running an older launcher/binary that enters sensor mode. Update the CLI; do not enroll a sensor to fix operator authentication. |
no such file or directory | Use an actual local path and quote spaces. |
| HTTP 401 | Check the server, key expiry/revocation, and copied key. Run config show to inspect saved settings without exposing the key. |
| HTTP 403 | Check key scopes, capture/team membership and account entitlements. |
| HTTP 413 | The deployment or reverse proxy rejected the upload size. Ask the deployment administrator to inspect upload limits. |
agent_model_not_eligible | The chosen AI connection/model is unavailable, unconfigured, or unapproved. Use --tui to choose an eligible route. |
HTTP 409 investigation_active | The requested workflow would replace shared Triage evidence while another investigation uses that capture. Wait for the reported investigation to finish, then retry. Independent Fast investigations can run in parallel when they do not replace shared evidence. |
| EOF / connection interrupted | Check service availability; retain the job ID and resume before creating another job. |
| Permission denied saving config | Inspect the owning user and configuration path. Use --config with a writable private path if needed; sensor credentials and CLI defaults are separate. |
Interpret evidence honestly
“Tool unavailable,” “read failed,” “not inspected,” and “inspected with no match” mean different things. A missing tool does not prove that the PCAP lacks the requested evidence. Look for the exact inspected frames, coverage, and reported runtime limitations before treating an answer as a negative finding.
See automation recipes for exit handling and durable job receipts, or the command reference for all common flags.
Decisions for automation
New reports can include data.decision, a validated, model-reported decision
separate from lifecycle and independent verification. decision.status=reported
means its structured data is available; not_reported means it is missing or
invalid. It does not mean the investigation found nothing.
For troubleshooting, decision.data includes failureCategory, likelyCause,
affectedEntities, networkResponsibility, confidence, nextDiagnosticStep,
and validationStep. Coverage distinguishes inspected_clean,
findings_present, partially_inspected, not_inspected, tool_failure, and
evidence_expired. These describe the model's reported inspected scope; they do
not certify complete capture processing or prove the cause.
For security, use assessment.securityVerdict for the threat assessment and
assessment.alertVerdict for the supplied alert. A false-positive alert can
coexist with other suspicious traffic: alertDisposition=close_false_positive
and incidentDisposition=escalate are compatible. recommendedDisposition
remains the incident recommendation. actionable=true can be reported in Fast
while independentVerification.status=not_run remains unchanged.
Store the investigation ID and data.revision when polling results. The revision
is an opaque content hash: unchanged results keep the same revision; changed
results get a different one. Use the pair as a consumer deduplication key, and
update the same external ticket according to your policy. This is not a built-in
ticket connector, webhook, or cross-capture incident identity. Consumers must
implement delivery retries and serialize ticket updates themselves.
EOF during API-key authentication
An EOF at /api/v2/api-access/token means the connection closed during token
exchange. It is not an HTTP 401/403 key rejection, and this invocation has not yet
uploaded the PCAP or submitted the investigation. A backend restart can cause it.
Wait for the backend to become ready, then rerun the same command; do not create
another key just because of EOF. Repeated EOFs require backend/proxy log inspection.
An interruption during investigation submission is different: the server might have accepted the job. Retain its receipt or job ID and resume that job instead.
Readable reports and structured results
Report milestones use submit_investigation_report to save readable Markdown
alongside validated decision fields. This is a backend Agent tool, not a CLI-only
feature: investigations started from an upload, an investigation dialog, the
Agent tab, or the CLI use it for their report stages. The same Agent submits the
report; this does not require a separate model call to extract decisions.
The CLI renders the saved investigation result. --format json returns its
structured fields and report narrative; --format markdown renders the narrative
with result metadata in front matter. It does not scrape decisions from the
displayed Markdown or print the raw tool response. Validation checks structure
and consistency, not factual correctness. An accepted report does not mean
independent verification ran.
Ordinary Agent chat and follow-up replies remain conversational Markdown, without mandatory report-tool submission. Triage-only runs do not request an AI report. Older explicit JSON report envelopes are displayed as their readable narrative; their decision JSON is not inserted into the conversation.
View results in the frontend
Open an investigation from AI Analyses or the capture's Agent tab, select its saved report, then choose Export → Watermarked JSON. This downloads the report, including structured decision fields when available. The frontend export is a report document with provenance metadata; it is not the same outer envelope as the CLI's investigation-result JSON.
Choose Structured results beside Report info to open a readable decision summary, with recommended actions first, independent verification status, and inspection coverage. Use Copy ticket summary for saved decisions, limitations, and a link to the report. In the capture Agent view, select a packet number to inspect the cited evidence. ATT&CK candidates are saved as structured data and shown with their limitations; they are model-reported mappings, not catalog or independent validation. The JSON tab shows the saved decision fields and offers Copy JSON; use Export for the complete report document. Report info continues to show metadata. Missing structured fields in older reports are explicitly marked as not reported, not interpreted as a negative finding.
Security review without an alert
The server derives alert applicability from the saved investigation request.
For a security review without an alert, assessment.alertVerification.applicable
is false; its ruleMatch and truePositive are null. The existing
assessment.truePositive is also null, and alertVerdict is not_applicable.
This does not mean the traffic is benign or that the assessment is missing:
use securityVerdict, actionable, and recommendedDisposition for the
security decision. Independent verification remains a separate status.
Structured results and CLI Markdown display Not applicable—no alert supplied.
If a model supplies alert-specific verdicts anyway, PacketSafari discards those
fields and records alert_fields_discarded_no_alert in validation warnings,
preserving the readable report and traffic assessment. A false-positive closure
recommendation without an alert becomes needs_review. These checks enforce
applicability; they do not establish that the model's traffic assessment is correct.
Provider failures
A failed investigation returns a nonzero CLI exit status. Its saved result includes
lifecycle.error; Markdown and the terminal error show the same recorded reason.
For example, HTTP 429 means the provider rejected requests because of a rate or
capacity limit. Check the provider's limits before starting another investigation.
Retrieving the failed job with --job-id does not retry model execution.
Cancellation acknowledgment is separate from worker termination. The stop request is sent to the investigation's current worker thread, including when the optional active-runtime identity is missing. Repeating cancellation for a stopped job re-sends that stop signal; it does not start new work.
