Skip to content

Bot markets write-through (PUT /markets) sends Record but API expects array → 400 (telemetry silently dropped) #8

Description

@jdkajewski

Summary

Found while running the full TS stack end-to-end (Postgres + @st/api + bot DRY_RUN) off the merged ts-rewrite-plan (PRs #3/#5/#6/#7).

The bot's bulk markets write-through fails validation on every call:

PUT /markets -> 400  FST_ERR_VALIDATION  "body must be array"
persistence: telemetry write dropped after retries (label=markets, status=400)

Root cause (contract mismatch)

  • Bot (packages/bot/src/clients/persistence.ts): putMarkets(markets: Record<string, Market>)fireAndForget('PUT', '/markets', markets, 'markets') sends a Record/object { wp: market, ... }.
  • API (packages/api/src/routes/markets.ts): PUT /markets bulk body schema is BulkPutBody = Type.Array([{ waypoint, data }]) — expects an array of {waypoint,data}.

So the shapes have never matched. Because markets telemetry is fire-and-forget with retry, the failure was swallowed (logged at warn, bot continues), which is why it went unnoticed.

Severity / scope

  • Pre-existing, not a regression from the galaxy/scan-budget/coverage PRs — the persistence client (wave-2 718a132) and the markets route schema have disagreed since before that work.
  • Low severity: telemetry only; the bot keeps trading. But it means bulk market snapshots are not being persisted to the API (per-waypoint PUT /markets/:wp uses a different, matching {data} schema and presumably still works).

Fix options

  1. Make putMarkets serialize the Record into the array shape [{ waypoint, data }] the bulk endpoint expects (preferred — keep the bulk endpoint).
  2. Or change PUT /markets to accept the Record shape.
    Add a contract test (bot persistence ↔ api schema) so the two can't drift again.

Repro

docker compose up (or local Postgres + @st/api + node packages/bot/dist/main.js with DRY_RUN=1); watch the API log for PUT /markets 400 'body must be array'.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions