status endpoint reports ready:false for every lead, always #150

Closed
opened 2026-08-23 12:50:24 +02:00 by ltms · 0 comments
Owner

What is wrong

GET /sessions/{id}/status reports ready: false for every lead, always, even when the daemon would deliver to that lead without any problem. The status endpoint and the delivery gate answer the same question ("can I deliver to this target?") from two different sources, and they disagree.

Why it happens

The delivery gate accepts a target that is either a present member or a known lead — Fleetd.java:576:

static Predicate<String> deliverableTo(MemberPresence presence, Supplier<Map<String, String>> leads) {
    return target -> presence.isPresent(target) || leads.get().containsKey(target);
}

The status endpoint drops the second half — FleetApp.java:521:

body.put("ready", presence.isPresent(id));

And presence is only ever recorded for a spawned member — FleetMcp.java:458:

static void markSpawnedMemberPresent(Principal caller, MemberPresence presence) {
    if (caller.isSpawnedMember()) {
        presence.markPresent(caller.terminal());
    }
}

A lead is not a spawned member, so markPresent is never called for one, so presence.isPresent(leadTerminal) can never return true. The ready field is therefore hardcoded to false for leads by construction — not by state.

Why it matters

It is a false negative on the one field an operator uses to decide whether a target can receive work, and it points the investigation in the wrong direction.

I hit this today while a lead genuinely was not receiving messages. The lead reported status: done, ready: false. The ready: false looked like the cause, so I spent time on the readiness path. It was a red herring: readiness was fine, and the real cause was that the lead was not in the leads map at all. A field that is always false cannot tell you anything, but it looks like it can.

This is the same shape as the note in Injector.java:71-74, which already warns about a target that is "not ready forever".

Suggested fix

Report ready from the same predicate the injector uses, rather than re-deriving it from one of its two inputs. deliverableTo is already package-private and pure, so the status handler can call it instead of presence.isPresent.

If the intent is that ready means specifically "has mounted the MCP" and not "is deliverable", then the two need different names, and the lead case needs its own field — because as it stands one word is doing both jobs and getting one of them wrong every time.

Test to add

A test that asserts a registered lead reports ready: true from the REST status endpoint. Note that a unit test on deliverableTo alone would pass today and would not catch this — the bug is that the caller does not use it. The test has to go through the status endpoint.

## What is wrong `GET /sessions/{id}/status` reports `ready: false` for **every lead, always**, even when the daemon would deliver to that lead without any problem. The status endpoint and the delivery gate answer the same question ("can I deliver to this target?") from two different sources, and they disagree. ## Why it happens The delivery gate accepts a target that is *either* a present member *or* a known lead — `Fleetd.java:576`: ```java static Predicate<String> deliverableTo(MemberPresence presence, Supplier<Map<String, String>> leads) { return target -> presence.isPresent(target) || leads.get().containsKey(target); } ``` The status endpoint drops the second half — `FleetApp.java:521`: ```java body.put("ready", presence.isPresent(id)); ``` And presence is only ever recorded for a **spawned member** — `FleetMcp.java:458`: ```java static void markSpawnedMemberPresent(Principal caller, MemberPresence presence) { if (caller.isSpawnedMember()) { presence.markPresent(caller.terminal()); } } ``` A lead is not a spawned member, so `markPresent` is never called for one, so `presence.isPresent(leadTerminal)` can never return true. The `ready` field is therefore hardcoded to `false` for leads by construction — not by state. ## Why it matters It is a false negative on the one field an operator uses to decide whether a target can receive work, and it points the investigation in the wrong direction. I hit this today while a lead genuinely was not receiving messages. The lead reported `status: done, ready: false`. The `ready: false` looked like the cause, so I spent time on the readiness path. It was a red herring: readiness was fine, and the real cause was that the lead was not in the leads map at all. A field that is always false cannot tell you anything, but it looks like it can. This is the same shape as the note in `Injector.java:71-74`, which already warns about a target that is "not ready forever". ## Suggested fix Report `ready` from the same predicate the injector uses, rather than re-deriving it from one of its two inputs. `deliverableTo` is already package-private and pure, so the status handler can call it instead of `presence.isPresent`. If the intent is that `ready` means specifically "has mounted the MCP" and not "is deliverable", then the two need different names, and the lead case needs its own field — because as it stands one word is doing both jobs and getting one of them wrong every time. ## Test to add A test that asserts a registered lead reports `ready: true` from the REST status endpoint. Note that a unit test on `deliverableTo` alone would pass today and would not catch this — the bug is that the *caller* does not use it. The test has to go through the status endpoint.
ltms closed this issue 2026-08-28 00:59:44 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: fleet/fleetd#150