From 880f1c2dcfb5e6cfcfcd0cb61c92c49cf4fa8cd6 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 22 Oct 2026 23:13:50 +0200 Subject: [PATCH] Worker: error body carries the typed code (closes gpu-busy-untyped-http) worker_error_body is the worker's one error wire shape; GpuBusy.code reaches the daemon as a field. GpuBusy is documented as placement only. Co-Authored-By: Claude Opus 5.5 --- scripts/kimodo-resident-worker.py | 7 +------ scripts/test_text_encoding.py | 6 ++++++ scripts/text_encoding.py | 12 +++++++++++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/scripts/kimodo-resident-worker.py b/scripts/kimodo-resident-worker.py index 846ace9..d699a2c 100644 --- a/scripts/kimodo-resident-worker.py +++ b/scripts/kimodo-resident-worker.py @@ -4,7 +4,6 @@ import json import os import shutil import time -import traceback from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from threading import Lock from types import SimpleNamespace @@ -394,11 +393,7 @@ class Handler(BaseHTTPRequestHandler): payload = json.loads(self.rfile.read(length).decode("utf-8") or "{}") write_json(self, 200, generate(payload)) except Exception as error: - write_json(self, 500, { - "ok": False, - "error": str(error), - "traceback": traceback.format_exc(), - }) + write_json(self, 500, text_encoding.worker_error_body(error)) def log_message(self, fmt, *values): print(f"{self.address_string()} - {fmt % values}", flush=True) diff --git a/scripts/test_text_encoding.py b/scripts/test_text_encoding.py index 65aa1e3..9619ae2 100644 --- a/scripts/test_text_encoding.py +++ b/scripts/test_text_encoding.py @@ -180,6 +180,12 @@ class ChildBoundary(unittest.TestCase): """) self.assertEqual(raised.exception.free_vram, 1234) + def test_worker_error_body_carries_the_code(self): + busy = te.worker_error_body(te.GpuBusy(GIB)) + self.assertIs(busy["ok"], False) + self.assertEqual(busy["code"], "gpu-busy") + self.assertIsNone(te.worker_error_body(RuntimeError("x"))["code"]) + def test_other_failures_name_the_exit_code_and_never_the_text(self): with self.assertRaises(RuntimeError) as raised: self.run_stub("import sys; sys.exit(1)", texts=(SECRET,)) diff --git a/scripts/text_encoding.py b/scripts/text_encoding.py index 668e529..572cdad 100644 --- a/scripts/text_encoding.py +++ b/scripts/text_encoding.py @@ -12,6 +12,7 @@ import subprocess import sys import tempfile import time +import traceback from dataclasses import dataclass from datetime import datetime, timezone from pathlib import Path @@ -33,7 +34,11 @@ LLAMA_BASE = "meta-llama/Meta-Llama-3-8B-Instruct" # the base model the mntp ad class GpuBusy(RuntimeError): - """The card has too little free VRAM to host the encoder; there is no CPU fallback.""" + """Placement refusal: too little free VRAM to host the encoder, and no CPU fallback. + + Whether heavy work may start at all is the daemon's tenancy gate, which sees the host; this is only + the child sizing its own placement from what torch can see. + """ code = "gpu-busy" @@ -49,6 +54,11 @@ def plan_placement(free_vram: int, mem_available: int) -> dict: return {0: free_vram - GPU_RESERVE, "cpu": max(mem_available - CPU_RESERVE, 0)} +def worker_error_body(error: BaseException) -> dict: + """The worker's one error wire shape: a typed code (GpuBusy.code, else None) beside the text.""" + return {"ok": False, "error": str(error), "code": getattr(error, "code", None), "traceback": traceback.format_exc()} + + def read_snapshot_revision(hf_home: Path, repo_id: str) -> str: """The commit the mounted Hugging Face cache resolves a repo's main ref to.""" ref = Path(hf_home) / "hub" / ("models--" + repo_id.replace("/", "--")) / "refs" / "main"