fix(cli): don't send dynamic IR bodies in registerApiDefinition request - #17426
fix(cli): don't send dynamic IR bodies in registerApiDefinition request#17426devin-ai-integration[bot] wants to merge 3 commits into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
There was a problem hiding this comment.
AI Review Summary
Small, focused fix: strips dynamic IR bodies from the registerApiDefinition request since FDR only needs the language keys to mint presigned S3 URLs. Logic and tests look correct. Only concern is back-compat with older/self-hosted FDR deployments that might still read the inline IR.
- 🔵 1 suggestion(s)
| export function toRegisterDynamicIRsInput( | ||
| dynamicIRsByLanguage: Record<string, DynamicIr> | undefined | ||
| ): Record<string, DynamicIr> | undefined { | ||
| if (dynamicIRsByLanguage == null) { | ||
| return undefined; | ||
| } | ||
| return Object.fromEntries(Object.keys(dynamicIRsByLanguage).map((language) => [language, {}])); |
There was a problem hiding this comment.
🔵 suggestion
Worth confirming that no deployed FDR version (including self-hosted registries pinned to older releases) consumes dynamicIRs[lang].dynamicIR from the registration body. If any do, this silently drops their dynamic snippets rather than failing loudly. If the S3 upload path is the only consumer everywhere, ignore.
There was a problem hiding this comment.
Checked this in fern-platform: no FDR version has ever read the IR body from the register request.
dynamicIRfirst appears in FDR source inchore(fdr): separate dynamic ir uploads(31cf0be, fern-platform#3378) — before that the field didn't exist in the register contract at all, so older/self-hosted registries ignore it as an unknown field.- Since it was introduced, the only consumer is
getDynamicIrsUploads→S3Service.getPresignedApiDefinitionDynamicIRsUploadUrls, which iteratesObject.entries(dynamicIRs)and discards the value (for (const [language, _dynamicIr] of ...)) to mint one presigned URL per language. Reads go throughloadDynamicIRFromS3, i.e. S3 is the only source of truth. - FDR's own registration tests already send
dynamicIR: {}(servers/fdr/src/__test__/local/services/api.test.ts), and the schema isz.object({ dynamicIR: z.unknown() }), so an empty object is valid input rather than a validation failure.
So dropping the bodies can't silently lose snippets — a registry that failed to receive the IR would fail at the upload/read step, not silently.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Description
Docs publishing fails with
PAYLOAD_TOO_LARGE/FST_ERR_CTP_BODY_TOO_LARGE(FDR's FastifybodyLimitis 100 MiB) for large APIs that have dynamic snippets configured for several SDK languages.publishDocswas sending the full dynamic IR inline for every language in theregisterApiDefinitionbody:FDR never reads those bodies —
getDynamicIrsUploads→getPresignedApiDefinitionDynamicIRsUploadUrlsiterates the map and ignores the value (for (const [language, _dynamicIr] of ...)), minting one presigned S3 URL per language; the CLI then uploads the IRs directly to S3 viauploadDynamicIRs. So the request body carried one redundant copy of the IR per language on top of the API definition itself, which is what pushed it over the limit.Now only the language keys are sent (
{ python: {}, go: {}, ... });dynamicIRis optional in the FDR contract (z.unknown()), and the localdynamicIRsByLanguagestill holds the bodies for the S3 upload step, so upload behavior is unchanged.Changes Made
toRegisterDynamicIRsInputwhich strips IR bodies while preserving language keyspublishDocsuses it for theregisterApiDefinitioncallTesting
toRegisterDynamicIRsInput.test.ts, 3 passing)turbo compile --filter=@fern-api/remote-workspace-runnerandpnpm check:fixcleanLink to Devin session: https://app.devin.ai/sessions/8f61e79cb12c453b8b22dd6809985f1c