Problem
int64ArgValue (non-strict, returns Int64?) still serves 20+ direct callsites in Server.swift for arg parsing. Each callsite has the same #22 bug shape:
guard let chatId = int64ArgValue(args, "chat_id") else {
return errorResult("chat_id is required")
}
When user passes .string("not-a-number") for chat_id / message_id / user_id / from_chat_id / reply_to_message_id, int64ArgValue silently returns nil → caller throws misleading "X is required" (the key was present, the value was the wrong type).
Affected callsites in Server.swift (count via grep -c 'int64ArgValue(' = 20 in Server.swift after #22-cluster ship):
| Line |
Tool |
Arg |
| L423 |
get_user |
user_id |
| L437 |
get_chat |
chat_id |
| L467 |
send_message |
chat_id |
| L471 |
send_message |
reply_to_message_id (optional — silent nil OK semantically) |
| L475-476 |
edit_message |
chat_id, message_id |
| L483 |
delete_messages |
chat_id |
| L491-492 |
forward_messages |
chat_id, from_chat_id |
| L499 |
search_messages |
chat_id |
| L508 |
get_chat_members |
chat_id |
| L515-516 |
pin_message |
chat_id, message_id |
| L523-524 |
unpin_message |
chat_id, message_id |
| L530 |
set_chat_title |
chat_id |
| L537 |
set_chat_description |
chat_id |
| L544 |
(continued) |
... |
| L559-560 |
(continued) |
... |
Sister concern surfaced during #22/#23/#25 cluster implementation (PR #32). The cluster scoped the fix to the parser layer (HandlerArgs.swift × 3 callsites) because cascading try int64ArgValueStrict through 20+ callsites is a separate blast-radius decision.
Type
bug (consistency — sister to #22)
Expected
Two viable approaches; diagnose-time decision:
Option A — Swap to strict at all callsites, propagate try
Each callsite becomes:
let chatId: Int64
do {
guard let id = try int64ArgValueStrict(args, "chat_id") else {
return errorResult("chat_id is required")
}
chatId = id
} catch {
return errorResultFromParse(error)
}
Pros: maximum precision per-callsite. Cons: 20+ × 8 lines of boilerplate.
Option B — Helper int64ArgValueRequired(args, key) → throws Int64
internal func int64ArgValueRequired(_ args: [String: Value], _ key: String) throws -> Int64 {
guard let value = try int64ArgValueStrict(args, key) else {
throw HandlerArgError(message: "\(key) is required")
}
return value
}
Each callsite becomes:
let chatId = try int64ArgValueRequired(args, "chat_id")
The outer handleToolCall do { ... } catch block already catches HandlerArgError via errorResultFromParse (PR #32 drive-by). Mechanically minimal.
Pros: minimal change per callsite; matches #22 helper-layer philosophy. Cons: slightly different error path (caught at outer level, not at case arm — but errorResultFromParse handles both message types identically).
Option C — Wrap each case arm in do/catch + use parser-style helper extraction
Move each tool's arg parsing into a parseXxxArgs function (mirroring parseGetChatHistoryArgs). High consistency benefit but ~20 new struct types + parser functions. Heavy.
Acceptance
Code Reference
Related
Source: surfaced during /idd-implement #25 reproduction (Step 5.7)
Problem
int64ArgValue(non-strict, returnsInt64?) still serves 20+ direct callsites inServer.swiftfor arg parsing. Each callsite has the same #22 bug shape:When user passes
.string("not-a-number")forchat_id/message_id/user_id/from_chat_id/reply_to_message_id,int64ArgValuesilently returns nil → caller throws misleading "X is required" (the key was present, the value was the wrong type).Affected callsites in
Server.swift(count viagrep -c 'int64ArgValue('= 20 in Server.swift after #22-cluster ship):get_useruser_idget_chatchat_idsend_messagechat_idsend_messagereply_to_message_id(optional — silent nil OK semantically)edit_messagechat_id,message_iddelete_messageschat_idforward_messageschat_id,from_chat_idsearch_messageschat_idget_chat_memberschat_idpin_messagechat_id,message_idunpin_messagechat_id,message_idset_chat_titlechat_idset_chat_descriptionchat_idSister concern surfaced during #22/#23/#25 cluster implementation (PR #32). The cluster scoped the fix to the parser layer (
HandlerArgs.swift× 3 callsites) because cascadingtry int64ArgValueStrictthrough 20+ callsites is a separate blast-radius decision.Type
bug (consistency — sister to #22)
Expected
Two viable approaches; diagnose-time decision:
Option A — Swap to strict at all callsites, propagate
tryEach callsite becomes:
Pros: maximum precision per-callsite. Cons: 20+ × 8 lines of boilerplate.
Option B — Helper
int64ArgValueRequired(args, key)→throws Int64Each callsite becomes:
The outer
handleToolCalldo { ... } catchblock already catchesHandlerArgErrorviaerrorResultFromParse(PR #32 drive-by). Mechanically minimal.Pros: minimal change per callsite; matches #22 helper-layer philosophy. Cons: slightly different error path (caught at outer level, not at case arm — but errorResultFromParse handles both message types identically).
Option C — Wrap each
casearm in do/catch + use parser-style helper extractionMove each tool's arg parsing into a
parseXxxArgsfunction (mirroringparseGetChatHistoryArgs). High consistency benefit but ~20 new struct types + parser functions. Heavy.Acceptance
Server.swiftreject.string("not-numeric")with"X must be an integer; got \"...\""(parity with chat_id type-mismatch error message misleads (silently shows 'is required' instead of type error) #22 fix)reply_to_message_id) preserve nil-on-absent semanticsget_user,send_message,pin_message)Code Reference
Sources/CheTelegramAllMCPCore/Server.swiftL423/437/467/471/475-476/483/491-492/499/508/515-516/523-524/530/537/544/559-560Sources/CheTelegramAllMCPCore/HandlerArgs.swift:int64ArgValueStrict(from chat_id type-mismatch error message misleads (silently shows 'is required' instead of type error) #22 cluster, PR fix(all-mcp): parser-consistency cluster — int64ArgValueStrict + parseLimit + dump default cap (#22, #23, #25) #32)Related
Source: surfaced during /idd-implement #25 reproduction (Step 5.7)