aaif-goose / aaif-goose/goose

Recipe validation is inconsistent across three paths: manage_schedule reports "Invalid YAML" for valid YAML, and schedule add does not validate at all

Abierto
#11,227 12 comentarios 0 reacciones 1 asignado Reclamado por @DOsinga Ver en GitHub
Lenguaje dominante
Rust
Estrellas
54.2k
Forks
6.2k
Merge medio
3 d 2 h
PR fusionados (30 d)
262

Descripción

**Version:** goose 1.46.0 (Goose.app and its bundled CLI), macOS 26.5.1, x86_64

Split out of #11164 at @A1exZabr's suggestion — it's a different subsystem and a different failure, and it stands on its own. @A1exZabr independently reproduced this on 1.46.0.

**Context on the reporter:** I'm not a developer. I'm using Goose to build a personal, fully local, automated home assistant on my own machine, and I found and investigated this with the help of Claude Code. I hit it by asking my assistant for a daily reminder and watching it fail in a way it couldn't recover from.

## Summary

The same file gets three different verdicts from three code paths in the same binary. The file below is well-formed YAML — it parses cleanly under an independent parser — but is not a valid Goose recipe, because it's missing `title`:

```yaml
name: drink_warm_water
run:
command: |
echo "Drink warm water"
schedule:
cron: "0 6 * * *"
timezone: "Asia/Kolkata"
```

| Path | Result |
|---|---|
| `goose recipe validate` | `✗ recipe file is invalid: missing field 'title'` |
| `platform__manage_schedule` (`action: create`) | `-32603: Invalid YAML recipe` |
| `goose schedule add` | **accepted silently** — job created, listed as `IDLE` |

## Two distinct problems

### 1. `manage_schedule` reports the wrong layer and discards the reason

`Invalid YAML recipe` is wrong on both counts: the YAML is valid, and the actual reason — a missing required field — is thrown away. The same binary produces `missing field 'title'` on the other two paths, so the information exists and is simply not carried through.

This matters most for the caller that can act on it. `manage_schedule` is the tool an *agent* calls, and an agent is uniquely positioned to read a precise error and fix the file itself. Instead it gets strictly less diagnostic information than a human running the CLI.

**What that looked like in practice.** I asked my assistant to set up a daily 6am reminder. It wrote the recipe above, using a schema it invented — entirely its own mistake, not a Goose bug. It called `manage_schedule`, got `Invalid YAML recipe`, and had no idea what was wrong. It edited the file, retried with the same invented schema, failed identically, then gave up and offered me three manual workarounds. Had the error said `missing field 'title'`, the retry would very likely have succeeded.

The user-visible outcome: I asked for a reminder and got an explanation of why I couldn't have one.

### 2. `goose schedule add` performs no validation

```
$ goose schedule add --schedule-id yamlerrtest --cron "0 6 * * *" --recipe-source ./bad.yaml
✅ Using standard 5-field cron format: 0 6 * * *
Scheduled job 'yamlerrtest' added.

$ goose schedule list
- ID: yamlerrtest
Status: ⏹️ IDLE
Cron: 0 6 * * *
Last Run: Never
```

It copies the file into `scheduled_recipes/` and reports success. The job sits in the schedule looking healthy, and fails only when its cron fires:

```
$ goose schedule run-now --schedule-id yamlerrtest
Error: Failed to run schedule 'yamlerrtest' now:
AnyhowError(Job 'yamlerrtest' failed: Invalid recipe: missing field `title`)
```

Note that the run-time error *does* carry the precise reason. So of the three paths, the two that could prevent the problem are the two that don't report it usefully, and the one that reports it well is the one that runs at 6am when nobody is watching.

For a desktop user, a scheduled job that fails at its cron time fails somewhere they will never look. (Related: #11164 covers what that silent-failure state looks like once you're in it.)

## Expected

- `manage_schedule` should return the same error the validator produces, naming the field.
- `schedule add` should validate the recipe before accepting the job, and refuse with that same message.

Neither requires new diagnostics — only carrying through the message Goose already generates.

## Reproduction

1. Save the YAML above as `bad.yaml`.
2. `goose recipe validate bad.yaml` → `missing field 'title'`.
3. Ask an agent session to schedule it, or call `platform__manage_schedule` with `action: create` → `-32603: Invalid YAML recipe`.
4. `goose schedule add --schedule-id t --cron "0 6 * * *" --recipe-source bad.yaml` → succeeds.
5. `goose schedule run-now --schedule-id t` → fails with `missing field 'title'`.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.