From cca67d0748c3bff6bfb8c59212ead266a9de7322 Mon Sep 17 00:00:00 2001 From: "MagicMock/mock.effective_git_name/128893997444000" Date: Sat, 16 May 2026 19:35:18 +0000 Subject: [PATCH] fix(pebble): catch YAML parse errors in discover_skills; log worker failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `_parse_skill` raises `yaml.scanner.ScannerError` (a `YAMLError`, not a `ValueError` or `OSError`) when a skill frontmatter contains an unquoted colon in a value (e.g. `Triggers: "..."` inside a description field). `discover_skills` only caught `(ValueError, OSError)`, so the error escaped, propagated out of `process_job` before the inner try/except, and was silently swallowed by `except Exception: pass` in `worker_loop` — with no log entry. Every subsequent command failed the same way, leaving the worker alive but effectively dead (blocked at `await queue.get()` after draining all failing jobs). - `discover_skills`: widen catch to `Exception` so any malformed skill file is warned and skipped instead of crashing the worker. - `worker_loop`: replace silent `pass` with `log.exception(...)` so unexpected errors from `process_job` are always visible in logs. Co-Authored-By: Claude Sonnet 4.6 --- src/clayde/webhook/skills.py | 2 +- src/clayde/webhook/worker.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/clayde/webhook/skills.py b/src/clayde/webhook/skills.py index bec35d7..780460a 100644 --- a/src/clayde/webhook/skills.py +++ b/src/clayde/webhook/skills.py @@ -108,7 +108,7 @@ def discover_skills(root: Path = SKILLS_ROOT) -> list[Skill]: for path in files: try: skill = _parse_skill(path) - except (ValueError, OSError) as e: + except Exception as e: log.warning("Failed to parse skill %s: %s", path, e) continue if skill.name in seen: diff --git a/src/clayde/webhook/worker.py b/src/clayde/webhook/worker.py index 3bb577e..d9e79e6 100644 --- a/src/clayde/webhook/worker.py +++ b/src/clayde/webhook/worker.py @@ -138,5 +138,4 @@ async def worker_loop(queue: JobQueue, *, timeout_s: int, kb_path: str) -> None: try: await process_job(job, timeout_s=timeout_s, kb_path=kb_path) except Exception: - # process_job already emitted a notification + logged. - pass + log.exception("[%s] unhandled error in process_job", job.id)