ubicloud: usage is an awk syntax error on macOS, which also disables the vCPU quota preflight
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 88/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- awk, bash, typescript
- Domain
- cli
Research direction
Read scripts/ubicloud/ubi-runner.sh around cmd_usage and quota_preflight, then inspect test/ubicloud-runner.test.ts and the macos-named-regressions list in .github/workflows/free-tests.yml. Run the Ubicloud runner tests on macOS if available. Done means usage prints the expected totals without an awk syntax error and the quota preflight refuses an over-limit request.
Written by the indexing model from the issue text.
Description
What happened
On macOS, gstack-ubi usage fails with an awk syntax error and exits 2:
awk: syntax error at source line 4
context is
for (o in cpu) printf "%-14s %4d %6d%s\n", o, vms[o], cpu[o], o >>> == <<<
awk: illegal statement at source line 4
awk: illegal statement at source line 4
The larger effect is on up: quota_preflight reads the total from cmd_usage, gets an empty string, and returns 0. So on macOS the vCPU preflight never refuses: with 20 vCPUs in use, a 16-vCPU ceiling (UBI_QUOTA_VCPUS=16) and a standard-4 request, it lets the create through; with the line fixed, it dies with "vCPU quota exhausted" as intended.
Cause
for (o in cpu) printf "%-14s %4d %6d%s\n", o, vms[o], cpu[o], o == me ? " (you)" : "" | "sort -k3,3nr"
macOS ships the one-true-awk (/usr/bin/awk, "awk version 20200816"), whose grammar rejects an unparenthesized == inside a print/printf argument list. The | "sort" redirect is not the trigger; this fails too:
/usr/bin/awk 'BEGIN { o = "a"; me = "a"; printf "%s%s\n", o, o == me ? " (you)" : "" }'
CI does not see it: free-tests is green on 047dad78, and test/ubicloud-runner.test.ts runs only on the Linux shards because it is not in the macos-named-regressions list.
Steps to reproduce
On macOS, from a gstack checkout at 047dad78 (no Ubicloud account needed; a local stand-in answers POST /cli for a project with two VMs):
cat > /tmp/fake_ubi_two.py <<'EOF'
# Answers POST /cli for a project with two VMs: one standard-4 owned by
# lane7, one standard-16 that this runner did not name.
import json, sys
from http.server import BaseHTTPRequestHandler, HTTPServer
class H(BaseHTTPRequestHandler):
def do_POST(self):
argv = json.loads(self.rfile.read(int(self.headers["Content-Length"])))["argv"]
if argv[:2] == ["vm", "list"]:
body = "eu-central-h1 ubirun-lane7-1761900000-ab12-t3\neu-north-h1 someone-elses-vm\n"
else:
body = "size: standard-4\n" if "lane7" in argv[1] else "size: standard-16\n"
b = body.encode()
self.send_response(200); self.send_header("Content-Length", str(len(b))); self.end_headers(); self.wfile.write(b)
def log_message(self, *a): pass
HTTPServer(("127.0.0.1", 18733), H).serve_forever()
EOF
python3 /tmp/fake_ubi_two.py & srv=$!; sleep 1
UBICLOUD_API_URL=http://127.0.0.1:18733 UBICLOUD_API_KEY=offline UBI_RUNNER_STATE=$(mktemp -d) UBI_OWNER=lane7 \
bash scripts/ubicloud/ubi-runner.sh usage; echo "exit=$?"
kill $srv
Expected:
OWNER VMS VCPUS
(other) 1 16
lane7 1 4 (you)
total 2 20
Actual: the syntax error above, exit 2.
Proposed fix
Parenthesize the ternary (valid in every awk):
--- a/scripts/ubicloud/ubi-runner.sh
+++ b/scripts/ubicloud/ubi-runner.sh
@@ -381,7 +381,7 @@
vms[o]++; cpu[o] += n; total += n; count++ }
END {
printf "%-14s %4s %6s\n", "OWNER", "VMS", "VCPUS"
- for (o in cpu) printf "%-14s %4d %6d%s\n", o, vms[o], cpu[o], o == me ? " (you)" : "" | "sort -k3,3nr"
+ for (o in cpu) printf "%-14s %4d %6d%s\n", o, vms[o], cpu[o], (o == me ? " (you)" : "") | "sort -k3,3nr"
close("sort -k3,3nr")
printf "%-14s %4d %6d\n", "total", count, total
}'
Verified on macOS /usr/bin/awk 20200816: usage prints the expected table and exits 0, and quota_preflight (20 vCPUs used, ceiling 16, standard-4 requested) refuses with "vCPU quota exhausted". No other print/printf in scripts/ubicloud/*.sh has an unparenthesized comparison. Suggested guard: add test/ubicloud-runner.test.ts to the macos-named-regressions file list, which would also catch the pack issue, #3680. (The whole file has not been run on macOS here, so it may surface more than these two.)
Readiness report
Hit on the 1.91.333.0 install below; the repro above is against main at 047dad78 (1.91.357.0), where the line is unchanged. Home paths are shortened to ~, and the paths of local CLAUDE.md files are removed from the last check line.
gstack doctor
gstack doctor 1.91.333.0
ok install root ~/.claude/skills/gstack: claude global current (1.91.333.0), codex global current (1.91.333.0)
ok rescue refs none in ~/.claude/skills/gstack
ok state root ~/.gstack durable=yes (selected by default)
ok bun 1.4.4 at /opt/homebrew/bin/bun (floor 1.3.3, tested 1.4.2)
ok hooks 9 hook(s) parse
ok codex codex-cli 0.163.0; self-locate ok; model gpt-6.1-sol (source: ~/.codex/config.toml model)
ok codex probe cached MODEL_OK, 18m ago (not re-run; --live probes now)
not configured artifacts sync off; cross-machine artifacts sync is unavailable
ok browse bundle browse/dist built
ok binaries find-browse, design, pdf, gstack-global-discover launch (4 of 4)
ok cso native helper 1.91.333.0 (11c17d466af3)
ok claude code 2.1.303 (Claude Code) at ~/.local/bin/claude
ok session journal largest of 2: 1.6 MiB
ok guard log 816 decisions (61 denied)
ok CLAUDE.md no gstack section lists skills
14 ok, 0 warn, 1 not configured, 0 fail
Environment
- Host: Claude Code 2.1.303
- OS: macOS 26.6.2 (25G83), arm64;
/usr/bin/awk"awk version 20200816" - gstack: hit on 1.91.333.0, reproduced on
main047dad78(1.91.357.0)
- Dominant language
- TypeScript
- Stars
- 138k
- Forks
- 20.5k
- Avg merge
- 8h 37m
- Merged PRs (30d)
- 320
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from garrytan/gstack
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Northeastern-Electric-Racing/FinishLine#4660 ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
excaliburjs/Excalibur#3895 ·
Maintainers usually reply within 3 days
-
infer_audio_type only recognises one MPEG Layer III frame header, so most MP3 files are rejectedPossibly taken @Steve-20-ai claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Earn report crashes with "RangeError: Invalid time value" when a report row has an unparsable timestampPossibly taken @Gurkaran18 claimed this today. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
joinmarket-webui/jam#1588 ·
Maintainers usually reply within 3 days
-
BeOS .json missingOpen
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
mihaip/infinite-mac#475 ·