← Back to PRs

#10807: fix(config): coerce numeric meta.lastTouchedAt to ISO string

by mcaxtr open 2026-02-07 01:22 View on GitHub →
size: S trusted-contributor experienced-contributor
## Summary Fixes #10785 When the agent edits `openclaw.json` directly (bypassing `stampConfigVersion()`), it can write `meta.lastTouchedAt` as a numeric Unix timestamp (e.g. `1770394758161`) instead of an ISO 8601 string. This causes Zod schema validation to reject the config on next startup, preventing the gateway and TUI from launching. The `doctor --fix` command also can't recover because validation fails before any fix logic runs. **Root cause:** The Zod schema defined `lastTouchedAt: z.string().optional()`, rejecting numeric values. **Fix:** Accept both strings and numbers via `z.union()`, coercing valid numeric timestamps to ISO strings via `.transform()`. Out-of-range numbers (e.g. `1e20`) are reported as validation errors via `ctx.addIssue()` instead of throwing, preserving `safeParse` error-reporting behavior. ## Changes - `src/config/zod-schema.ts`: Replace `z.string().optional()` with a `z.union([z.string(), z.number().transform(...)])` that safely coerces valid numeric timestamps to ISO strings - `src/config/config.meta-timestamp-coercion.test.ts`: 4 new tests covering numeric coercion, string passthrough, out-of-range rejection, and absent field ## Test plan - [x] Write failing test reproducing the bug (numeric timestamp rejected) - [x] All 4 new tests fail before fix, pass after - [x] Out-of-range numeric timestamps (e.g. `1e20`) return `{ ok: false }` instead of throwing `RangeError` - [x] Full CI gate passes locally (`pnpm build && pnpm check && pnpm test` — 219 tests, 0 failures) <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> - Updates `OpenClawSchema` to accept `meta.lastTouchedAt` as either a string or a numeric Unix timestamp, coercing valid numbers to ISO strings during validation. - Adds a new Vitest suite validating numeric coercion, string passthrough, out-of-range numeric rejection, and optional-field behavior. - Change is localized to config schema validation and a focused regression test for startup validation failures caused by agent-written configs. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - Changes are narrowly scoped to config schema validation and add regression tests. The coercion uses Zod issues (not throws) to preserve safeParse behavior, and string inputs remain backward-compatible as before. - No files require special attention <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs