Skip to content

Share with a friend fails: grant_bot_to_friend rejects the call with "received undefined at friend_owner_id" #592

Closed

Description

@Birfy

What happened? / 发生了什么?

In a Bot's settings → 分享 → Share with a friend, clicking Share next to an existing friend fails and the raw MCP error is shown under the row:

MCP error -32602: Input validation error: Invalid arguments for tool grant_bot_to_friend: Invalid input: expected string, received undefined at friend_owner_id

Nothing is shared; People with access stays empty. Seen on a re-share after Revoke (Scout was shared with Lin, revoked, then Share clicked again for Lin).

This is not #563: there the server had no grant_bot_to_friend tool at all (Tool grant_bot_to_friend not found). Here the tool exists (local Bot Social master @ 58afc9f, which added it for Birfy/bot-social#34) and rejects FlyBot's arguments.

Expected: Share grants the Bot to that friend (People with access shows them), or, if the server cannot identify the friend, a plain-language error, never a raw MCP error -32602 string.

Likely cause (code reading, origin/main 645a291)

A contract mismatch between FlyBot (#500 / PR #516) and Bot Social's grant_bot_to_friend:

  • FlyBot only sends friend_owner_id when it has one, and otherwise sends only friend_home:
    • plugins/social/src/mcp-client.js:438-465 (grantBotToFriend: friend_owner_id only if friendOwnerId, plus friend_home).
    • plugins/social/src/social.js:2262-2276 (social/share-with-friend: oid = friendOwnerId || ownerId, often undefined).
    • The friend list's ownerId comes from peerView at plugins/social/src/social.js:1854 (item.peer?.owner_id || item.friend_owner_id || item.owner_id) and is copied at social.js:2226; the client passes it at plugins/social/client.js:2130-2134.
  • Bot Social never returns an owner id for a friend, so ownerId is always undefined: list_friends → listRelationships builds peer with publicBot() (Birfy/bot-social src/platform.ts:1419-1434, publicBot at platform.ts:108-111 returns bot_id, handle, display_name, owner_display_name, owner_verified — no owner_id).
  • Bot Social's tool schema requires friend_owner_id and does not know friend_home: src/owner-mcp.ts:234-236 (inputSchema: { bot_id: z.string(), friend_owner_id: z.string() }), src/platform.ts:1060 (friend_owner_id required).
  • The REST fallback path also does not match: FlyBot posts /v1/bots/:id/grants/to-friend (mcp-client.js:458), the server route is POST /v1/bots/:id/grants with friend_owner_id (src/server.ts:75). The fallback only runs on unknown-tool anyway (isUnknownTool, mcp-client.js:155-166), so a validation error goes straight to the UI.
  • The plugin tests mock a server that accepts friend_home and sends owner_id on the peer (plugins/social/test/social.test.js:8295, :8351, :8381), which the real server does neither — the LESSONS 2026-10-18 "mock answer must have the shape the real server sends" pattern.

The root cause is partly on the Bot Social side (no owner id on list_friends peers; no friend_home input). Filed here per the rule that routines do not open issues on other repos; the owner decides whether a companion change goes to Bot Social.

Change scope (suggested, needs owner decision because it is the sharing surface)

Either (a) Bot Social exposes the friend's owner id on list_friends peers (or accepts friend_home / the friend's handle in grant_bot_to_friend) and FlyBot sends it, or (b) FlyBot resolves the owner id another way before calling. In both cases: align the REST fallback route with the server, map a -32602 validation error to a readable message, and replace the mock with the real server's answer shape (naming the Bot Social commit).

Screenshot / 截图

Not attached (kept local). Captured on the recording box as /workspace/slides/flybot-intro-834wrk/issue-evidence/share-with-friend-error.png: Scout's settings, "Share with a friend · Lin @lin.home · Share", the red error above. Also noted in the demo-5c caveat of the demo video index.

Steps to reproduce / 复现步骤

  1. Run two homes (A = Danyang, B = Lin) against Bot Social master @ 58afc9f; make them friends via an invite link.
  2. On A, open a Bot (Scout) → settings → 分享 → Share with a friend → Share for Lin. (In the recording, Scout had been shared and then Revoked first.)
  3. The row shows MCP error -32602: … grant_bot_to_friend … expected string, received undefined at friend_owner_id.

Diagnostics / 诊断信息

FlyBot main @ 4f6a53d (code paths unchanged on 645a291), @deepseek-ai/dsh 0.2.0-rc.2 (dsh web), @flybot/social + @flybot/tree linked from the checkout, local Bot Social Birfy/bot-social master @ 58afc9f with a throwaway data dir, mock model core/dev/mock-llm.mjs, headless Chrome, zh-CN, 1440×900. Found while recording demos, not by the self-test routine.

Privacy / 隐私

  • This report has no API keys, tokens or personal data.

Activity

  1. added
    bugSomething isn't working
    area:socialFriends, invites, grants, Bot Social
    on Oct 21, 2026
  2. Birfy commented on Oct 21, 2026

    @Birfy
    CollaboratorAuthor

    Triaged (maintenance round, 2026-10-21): a real bug, but needs-info before it can be agent-ready — the failing validation is on Bot Social's side (grant_bot_to_friend requires friend_owner_id; FlyBot only ever has friend_home for a friend, because Bot Social's friend list does not return an owner id).

    So the fix is either server-side in Birfy/bot-social (accept the friend by friend_home / return owner_id) — which then needs a deploy decision — or FlyBot sends the field the server wants. I will read the Bot Social side first. The other half of the expected behavior (never show a raw MCP error -32602, show a plain-language error) is in FlyBot's scope either way.

  3. added
    needs-infoWaiting for the reporter or a maintainer decision
    on Oct 21, 2026
  4. Birfy commented on Oct 21, 2026

    @Birfy
    CollaboratorAuthor

    Confirmed against Birfy/bot-social master @ 58afc9f1 (the commit in the report) — the mismatch is real and it is a contract gap on the Bot Social side, not a FlyBot argument bug. Verified, not inferred:

    • src/owner-mcp.ts:235 — grant_bot_to_friend inputSchema: { bot_id: z.string(), friend_owner_id: z.string() }. friend_home is not in the schema and is stripped before the handler, so the call fails validation with exactly the -32602 … received undefined at friend_owner_id in the report. src/platform.ts:1060 asserts the same again (friend_owner_id required).
    • src/platform.ts:108-111 (publicBot) — a peer is { bot_id, handle, display_name, owner_display_name, owner_verified } (plus avatar/color for an active friend). friendsOverview (:1646) and listBotGrants (:1188) both use it, so no owner_id is ever returned for a friend, for any relationship status. friend_owner_id can only come from the friend out of band (their own whoami, as the tool description says).
    • grep friend_home over src/platform.ts, src/server.ts, src/owner-mcp.ts — 0 hits. There is no handle path anywhere.
    • src/server.ts:75 — the REST route is POST /v1/bots/:id/grants with friend_owner_id; FlyBot's fallback posts /v1/bots/:id/grants/to-friend (plugins/social/src/mcp-client.js:458), which does not exist. It only runs on an unknown tool / missing endpoint (isUnknownTool), so a validation error never reaches it.

    So today the flow cannot work for any friend who has not told you their owner id, whatever FlyBot sends.

    Options (all need an owner decision — this is the sharing surface):

    • A. Server accepts the friend's peer bot id (friend_bot_id) — list_friends already returns peer.bot_id, so the owner side always has it. Resolve the peer → its owner, then keep the existing friendships.length > 0 assertion unchanged. Small, unambiguous, exposes no owner ids.
    • B. Server accepts friend_home (the peer's handle; FlyBot sends it today at mcp-client.js:446) and resolves it the same way. A server-only change would make the current FlyBot build work as-is; a handle is a weaker key than a bot id, so A is the better form.
    • C. Server returns the friend's owner_id on active-friend peers. Bigger privacy change (every friend's connector would see it) and more plumbing on the FlyBot side; not needed for the fix.
    • D. FlyBot-only: do not offer Share for a friend whose owner id we do not have, and point at the out-of-band id. No server change, but the feature stays manual.

    Whichever is chosen, two FlyBot-side follow-ups belong with it: fix the REST fallback to POST /v1/bots/:id/grants (or drop it), map a -32602 validation error to a plain-language line instead of the raw MCP error string, and replace the mock in plugins/social/test/social.test.js with the real server's peer shape (LESSONS 2026-10-18). I have not changed anything: the Bot Social repo has no open issue or PR for this and no deploy will happen without the owner's explicit go-ahead.

  5. added
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    and removed
    needs-infoWaiting for the reporter or a maintainer decision
    on Oct 21, 2026
  6. removed
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Oct 21, 2026
  7. Birfy commented on Oct 21, 2026

    @Birfy
    CollaboratorAuthor

    Closing conclusion — option A, landed on both ends. The server now accepts the peer's bot_id, and no owner_id is exposed anywhere new.

    • Server (Birfy/bot-social) — PR Birfy/bot-social#38, squash 82bcc0c1. grant_bot_to_friend takes friend_bot_id (the peer bot_id from list_friends, or its handle), derives the owner from it and keeps the existing "must be an active friend" assertion, now filtered to that Bot; friend_owner_id still works, and both together must name the same owner. POST /v1/bots/{id}/grants forwards the new field. No new field is returned to a peer, so the privacy surface is unchanged. Marked awaiting-deploy — not deployed, that needs the owner's go-ahead.
    • FlyBot — PR Share with a friend by the peer Bot id (#592) #600, squash f2b461f0 (T3, self-PASS at 80849705). The share sends friend_bot_id; the REST fallback posts to the route the server really has, POST /v1/bots/:id/grants (it was /grants/to-friend); an invalid-input refusal now reads as one plain English line instead of the raw JSON-RPC text; the plugin's test server serves the real peer shape (a bot_id, no owner_id).
    • Tests: plugins/social 274/274, and 268/274 with the three source files reverted; the server's test/grant_bot_to_friend.test.ts 6/6, 4/6 reverted.

    Until the server build is deployed, a share still answers with "Bot Social did not accept that share request. Its server may need an update; invite links still work." — i.e. the same failure, now explained instead of showing MCP error -32602.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:socialFriends, invites, grants, Bot SocialbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions