fix: handle shell command parsing errors instead of silently failing#132
fix: handle shell command parsing errors instead of silently failing#132
Conversation
Previously, shell_words::split() errors were silently converted to empty command vectors via unwrap_or_default(), which could cause daemons to start with no command instead of failing visibly. Now parsing errors are logged and the operation is skipped/aborted, making debugging much easier when commands contain syntax errors. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| Err(e) => { | ||
| error!("failed to parse command for cron daemon {}: {}", id, e); | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Repeated cron trigger errors without state update
Low Severity
When shell_words::split fails in check_cron_schedules, the code logs an error and executes continue without updating daemon state. For cron daemons with Always or Finish retrigger modes, the should_run condition will remain true on subsequent cron triggers, causing repeated error logging on every schedule match. Unlike the retry case, cron triggers are schedule-based (checked every 60 seconds), so impact is lower but the error will recur indefinitely for permanent config errors.
- Mark daemon as exhausted when command parsing fails in retry loop, preventing infinite retry attempts every 10 seconds - Return correct HTML structure based on from_detail context in web route, fixing broken table structure when called from list page Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
Pass the daemon's current status to upsert_daemon when marking as exhausted due to command parse failure, instead of using Default which would overwrite Errored status with Stopped. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## 🤖 New release * `pitchfork-cli`: 0.3.0 -> 0.3.1 <details><summary><i><b>Changelog</b></i></summary><p> <blockquote> ## [0.3.1](v0.3.0...v0.3.1) - 2026-01-19 ### Added - implement daemon dependency resolution ([#135](#135)) - add restart command to CLI ([#134](#134)) ### Fixed - restart command preserves daemon dependency configuration ([#142](#142)) - add missing depends field to restart command ([#136](#136)) - set IPC socket permissions to 0600 for security ([#133](#133)) - handle shell command parsing errors instead of silently failing ([#132](#132)) ### Other - reduce unnecessary daemon cloning in loops ([#144](#144)) - use periodic log flushing instead of per-line ([#139](#139)) - refresh only tracked PIDs instead of all processes ([#141](#141)) - cache compiled regex patterns ([#143](#143)) ### Security - add rate limiting to IPC server ([#137](#137)) - canonicalize config paths to prevent symlink exploitation ([#138](#138)) - add centralized daemon ID validation ([#140](#140)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/release-plz/release-plz/). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Prepares the 0.3.1 release and updates metadata/documentation accordingly. > > - **Changelog**: Adds `0.3.1` entry detailing added dependency resolution, new `restart` command, fixes, performance tweaks, and security hardening > - **Version bumps**: Updates `version` to `0.3.1` in `Cargo.toml`, `Cargo.lock`, `docs/cli/commands.json`, `docs/cli/index.md`, and `pitchfork.usage.kdl` > - **Docs regen**: Refreshes CLI docs/spec to reflect the new version (no behavioral changes in this diff) > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9f9d386. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## 🤖 New release * `pitchfork-cli`: 1.0.0 <details><summary><i><b>Changelog</b></i></summary><p> <blockquote> ## [1.0.0](https://github.com/jdx/pitchfork/releases/tag/v1.0.0) - 2026-01-19 ### Added - implement daemon dependency resolution ([#135](#135)) - add restart command to CLI ([#134](#134)) ### Fixed - restart command preserves daemon dependency configuration ([#142](#142)) - add missing depends field to restart command ([#136](#136)) - set IPC socket permissions to 0600 for security ([#133](#133)) - handle shell command parsing errors instead of silently failing ([#132](#132)) ### Other - bump version to 1.0.0 ([#147](#147)) - release v0.3.1 ([#121](#121)) - reduce unnecessary daemon cloning in loops ([#144](#144)) - use periodic log flushing instead of per-line ([#139](#139)) - refresh only tracked PIDs instead of all processes ([#141](#141)) - cache compiled regex patterns ([#143](#143)) ### Security - add rate limiting to IPC server ([#137](#137)) - canonicalize config paths to prevent symlink exploitation ([#138](#138)) - add centralized daemon ID validation ([#140](#140)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/release-plz/release-plz/). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Prepares the 1.0.0 release and updates `CHANGELOG.md` with the finalized notes. > > - Adds `1.0.0` section: daemon dependency resolution, new CLI `restart` command, fixes for dependency preservation and shell parsing, secure IPC socket perms, plus performance/maintenance updates > - Documents security hardening: IPC rate limiting, config path canonicalization, centralized daemon ID validation > - Retains prior `0.3.1` notes for historical context > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4182984. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Summary
shell_words::split().unwrap_or_default()with proper error handlingThis prevents daemons from starting with no command when there's a syntax error in the
runfield, making debugging much easier.Test plan
🤖 Generated with Claude Code
Note
Improves resilience and debuggability when parsing daemon
runcommands frompitchfork.toml.unwrap_or_default()with explicitshell_words::spliterror handling insupervisor.rsfor retries, boot starts, and cron triggers; log errors and skip runs (retry path marks retries exhausted to avoid loops)web/routes/daemons.rs: on Start, parse command with error handling and return a contextual error block/row (depending on detail/list view) instead of proceedingWritten by Cursor Bugbot for commit 0684f45. This will update automatically on new commits. Configure here.