Programming & Scripting Errors Jul 13, 2026

February Fest Live-Ops Hourly jsonl jq Append Fails When Row Missing build_label - How to Fix

Fix february_fest_live_ops_hourly_log.jsonl jq append when build_label is missing. J3 crosswalk, shared append script, jsonl integrity checks, and BUILD_RECEIPT february_fest_live_ops_hourly_ok for February 2027 live week.

By GamineAI Team

February Fest Live-Ops Hourly jsonl jq Append Fails When Row Missing build_label - How to Fix

Problem: During February 2027 Steam Next Fest live week, facilitators (or a GitHub Actions cron) still append lines to february_fest_live_ops_hourly_log.jsonl, but verify_february_live_ops.sh exits 3, jq hourly row-diff fails, or Thursday row review stays RED because one or more hourly rows are missing build_label (empty string, null, or the field renamed to build_id / version only).

Who is affected now: Unity / multi-engine teams using Unity hourly jsonl append preflight (Guide #40) and Lesson 280. This is hourly writer schema recovery, not HOTFIX list blocking (Help HOTFIX exception), not fest-day depot mismatch after setlive (setlive case study / Help #38), and not SteamPipe “queued forever” (Help #14 forward).

Fastest safe fix: Stop stand-up GREEN theater → find bad jsonl lines → normalize writer to always emit build_label from Unity Application.version (or engine cousin) → rewrite LATEST receipt → run verify → append three consecutive good hours → set BUILD_RECEIPT february_fest_live_ops_hourly_ok: true.

Direct answer

Missing build_label on hourly jsonl means the append script (or a per-laptop copy) wrote a partial object. Thursday jq and verify_february_live_ops.sh J3 expect a non-empty label that is not a live-week dev string. Fix the shared writer, backfill broken lines, then prove three green cycles—do not flip february_fest_live_ops_hourly_ok by hand.

Why this issue spikes in February 2027 live week hour three

  1. Per-facilitator scripts drift — Someone ship a laptop one-liner that drops fields under time pressure.
  2. Field rename confusion — Steam depot buildid is not receipt build_label; writers mix them.
  3. Partial hours — “Nothing changed” shortcuts omit the label entirely instead of documenting delta: unchanged.
  4. Corrupt jsonl — Missing trailing newline or truncated JSON breaks tail -n 1 before J3 even runs.
  5. Editor vs player — Append runs from Editor Play with blank Application.version while players are on HOTFIX depot.

Symptoms and search phrases

  • verify_february_live_ops.sh exit 3 (J3 build_label policy).
  • jq: error / empty .build_label on FEBRUARY_LIVE_OPS_RECEIPT_LATEST.json.
  • Thursday review RED on february_fest_live_ops_hourly_ok after “successful” cron appends.
  • february_fest_live_ops_hourly_log.jsonl lines with "build_label":"" or no build_label key.
  • Stand-up paste shows prior-hour label while receipt hour_utc advanced.
  • GitHub Actions hourly job green but local verify red (artifact vs laptop path).

Root causes (check in order)

  1. Optional field in writer — schema treated build_label as nullable.
  2. build_id / Application.version only — wrong field name in jq compact object.
  3. Corrupt / truncated jsonl line — partial write without newline.
  4. jq assume full schema on prior hour — diff reads prior line with missing label and cascades.
  5. Unity smoke never exported — append invents snapshot without label (Guide #40 order violated).
  6. Bool flipped without verify — theater GREEN; CI still exit 3.

Beginner path (first 15 minutes)

Prerequisites: jq, write access to release-evidence/february-live/, Guide #40 scripts in repo (or paste from jq blog).

  1. List bad lines:
jq -c 'select((.build_label // "") | length == 0)' \
  release-evidence/february-live/february_fest_live_ops_hourly_log.jsonl
  1. Open FEBRUARY_LIVE_OPS_RECEIPT_LATEST.json → set build_label from the exported player footer / Unity Application.version.
  2. Run verify → append once with the shared append_february_live_ops_hour.sh.
  3. Repeat for the next two hours (or simulate with documented hour_utc bumps in dry-run branch).
  4. Promote BUILD_RECEIPT only after three exit 0 cycles.

Common mistake: Editing only BUILD_RECEIPT while leaving corrupt jsonl lines in place—Sunday closeout will still fail integrity checks.

Fastest safe fix path

Step 1 — Inventory bad hours

LOG=release-evidence/february-live/february_fest_live_ops_hourly_log.jsonl
# Lines missing or empty build_label
jq -c 'select((.build_label // "") | length == 0) | {hour_utc, fest_day, keys: keys}' "$LOG"
# Duplicate hour stamps (corruption cousin)
jq -s '[.[].hour_utc] | length as $n | unique | length == $n' "$LOG"

Move verified-bad lines aside (do not delete without backup):

cp "$LOG" "$LOG.bak-$(date -u +%Y%m%dT%H%M%SZ)"

Step 2 — Normalize the shared writer schema

Canonical compact object (must match Guide #40 / Lesson 280):

jq -c '{hour_utc, fest_day, build_label, february_fest_live_ops_hourly_ok, receipt_path: $rec}' \
  --arg rec "$REC" "$REC"

Required: build_label is a non-empty string matching live policy (fest-demo-2027-02-* / team convention)—never omit the key.

Reject laptop copies that write:

{"hour_utc":"...","fest_day":"D3","build_id":4829111}

build_id can live under snapshot if useful; J3 keys on build_label.

Step 3 — Repair LATEST receipt (J1–J3)

{
  "schema": "february_fest_live_ops_receipt_v1",
  "fest_window": "2027-02-next-fest-live",
  "fest_day": "D3",
  "hour_utc": "2027-02-18T18:00:00Z",
  "build_label": "february-fest-2027-live-rc2",
  "snapshot": {
    "hour_one_launch_rate": 0.38,
    "february_live_queue_wall_clock_ok": true,
    "fest_stream_overlay_safe_zone_ok": true
  },
  "row_diff": [
    {"field": "build_label", "before": "february-fest-2027-live-rc2", "after": "february-fest-2027-live-rc2", "delta": "unchanged"}
  ],
  "february_fest_live_ops_hourly_ok": false
}

Unity source of truth:

Debug.Log($"build_label={Application.version}");

Gate before append:

BL=$(jq -r '.build_label // empty' release-evidence/february-live/FEBRUARY_LIVE_OPS_RECEIPT_LATEST.json)
test -n "$BL" && [[ "$BL" != *dev* ]]

Step 4 — Verify + append (fail-closed)

REC=release-evidence/february-live/FEBRUARY_LIVE_OPS_RECEIPT_LATEST.json
./scripts/verify_february_live_ops.sh "$REC"
./scripts/append_february_live_ops_hour.sh "$REC"

Pass: verify prints OK (exit 0); jsonl gains a line with non-empty build_label.
Fail exit 3: fix label / HOTFIX crosswalk—do not append.

If label changed for a HOTFIX binary, file hotfix_id in receipt notes and align HOTFIX exception help—do not invent a silent label drift.

Step 5 — Three consecutive GREEN cycles + BUILD_RECEIPT latch

Cycle Check
1 verify 0 + append with label
2 Prior hour now has label; row_diff recomputes
3 No empty-label lines in last three jsonl rows

Then:

jq -e '
  [.[] | select(.hour_utc != null)]
  | .[-3:]
  | all(.[]; (.build_label // "") | length > 0)
' release-evidence/february-live/february_fest_live_ops_hourly_log.jsonl

Promote:

"february_fest_live_ops_hourly_ok": true,
"cousin_receipts": {
  "february_live_ops_latest": "release-evidence/february-live/FEBRUARY_LIVE_OPS_RECEIPT_LATEST.json",
  "february_live_ops_hourly_log": "release-evidence/february-live/february_fest_live_ops_hourly_log.jsonl"
}

Verification

Check Pass when
Scanner Zero empty-label lines in active fest window jsonl
Verify Exit 0 on LATEST
Append Last jsonl line includes build_label
Three-cycle Last three lines all labeled
BUILD_RECEIPT february_fest_live_ops_hourly_ok: true
Thursday Hourly column no longer RED for missing label

Alternative fixes (edge cases)

Branch A — Corrupt truncated line

Rewrite file from .bak excluding the bad last line; ensure every write ends with \n. Never use editors that strip final newlines on save.

Branch B — Label changed without HOTFIX row

J3 is correctly RED. Complete HOTFIX exception fix / Guide #41 cousin before claiming hourly GREEN.

Branch C — CI append green, laptop red

Artifact upload omitted FEBRUARY_LIVE_OPS_RECEIPT_LATEST.json contents; workflow invented empty label. Fail the job when test -n "$(jq -r .build_label "$REC")".

Branch D — March weekly schema accidentally used

march_post_fest_sprint_* paths during February fail J1—route back to february_fest_live_ops_receipt_v1 (Guide #40); March weekly is Guide #46 / Lesson 287 later.

Branch E — Sunday closeout already started

Backfill recoverable hours with honest labels; document unrecoverable gaps as waivers on Sunday closeout—do not invent labels from memory.

Prevention

  • One repo-pinned append_february_live_ops_hour.sh—delete facilitator copies.
  • Pre-append assert: non-empty build_label / not *dev*.
  • Cron only on fest live branch (Guide #40 if:).
  • Teach facilitators jq blog exit table (3 = label policy).
  • Latch Lesson 280 BUILD_RECEIPT milestone in the project course CI before D1.

Related problems

FAQ

Can we set february_fest_live_ops_hourly_ok true to unblock Thursday?
No—verify must exit 0 and last jsonl lines must carry real build_label values.

Is missing build_label the same as wrong Steam buildid?
No—buildid is SteamPipe; build_label is your team string. Both can be wrong independently.

Do we delete the whole jsonl file?
Prefer backup + surgical rewrite of bad lines; full delete loses Sunday closeout trail.

Unity team only?
Writer fields are engine-agnostic—map build_label from your visible version string.

Three cycles required?
Yes for this recovery article—one lucky hour can hide a still-broken writer.


Bookmark this fix for live-week hour three. Share it with whoever owns the append cron if the verify exit table saved your Thursday review.