{"record":{"id":"03067cd12aedfa99","repo":"moeru-ai/airi","slug":"invalid-request-body-03067c","errorCode":null,"errorMessage":"Invalid request body","messagePattern":"Invalid request body","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/provider-inference/src/providers/cloud/mimo-audio/index.ts","lineNumber":69,"sourceCode":"      }),\n    ],\n  }\n}\n\nfunction createMimoSpeechProvider(config: MimoSpeechConfig) {\n  const apiKey = config.apiKey?.trim() ?? ''\n  const baseUrl = normalizeBaseUrl(config.baseUrl)\n  const defaultModel = config.model || 'mimo-v2.5-tts'\n  const defaultVoice = config.voice || 'mimo_default'\n  const defaultFormat = config.format || 'wav'\n\n  return {\n    speech: () => ({\n      baseURL: baseUrl,\n      model: defaultModel,\n      fetch: async (_input: RequestInfo | URL, init?: RequestInit) => {\n        if (!init?.body || typeof init.body !== 'string')\n          throw new Error('Invalid request body')\n\n        const body = JSON.parse(init.body) as {\n          input?: string\n          model?: string\n          response_format?: string\n          style_prompt?: string\n          voice_sample?: string\n          voice?: string\n        }\n        const model = body.model || defaultModel\n        const format = body.response_format || defaultFormat\n        const stylePrompt = body.style_prompt?.trim() || config.stylePrompt?.trim() || ''\n        const voiceSample = body.voice_sample?.trim() || config.voiceSample?.trim() || ''\n        const userPrompt = model === 'mimo-v2.5-tts-voiceclone'\n          ? stylePrompt\n          : stylePrompt || 'Use a natural, clear speaking style.'\n\n        const audio: Record<string, string> = { format }","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/moeru-ai/airi/blob/f679616c34f1cf6d282c8d64264242af944b3fed/packages/provider-inference/src/providers/cloud/mimo-audio/index.ts#L51-L87","documentation":"The MiMo speech provider's custom fetch requires the outgoing request body to be a JSON string. When init.body is missing or not a string, the wrapper cannot parse the TTS options (input, model, voice, style) and throws instead of sending a broken request.","triggerScenarios":"Calling the MiMo speech API through a path that does not produce a string body: a custom fetch that supplies no body, a FormData/stream/Blob body, or calling the wrapped fetch directly without init.","commonSituations":"Middleware or proxy fetch wrapping that drops the body, invoking the fetch function manually for testing, or using an SDK client version that serializes bodies differently.","solutions":["Call the provider through its speech() API so the body is JSON-serialized before the wrapper runs","Inspect any custom fetch chain and ensure it forwards the original init.body string","Avoid overriding body with non-string types when configuring the speech client","In test code, always pass a JSON-string body when invoking the wrapper directly"],"exampleFix":"// before\nconst res = await customFetch(url) // no body\n// after\nconst res = await customFetch(url, { method: 'POST', body: JSON.stringify({ model, input, voice }) })","handlingStrategy":"validation","validationCode":"const body = init?.body\nif (typeof body !== 'string' || !body) throw new Error('MiMo speech request requires a JSON string body')\nJSON.parse(body)","typeGuard":"function hasStringBody(init?: RequestInit): init is RequestInit & { body: string } {\n  return typeof init?.body === 'string' && init.body.length > 0\n}","tryCatchPattern":"try {\n  const audio = await provider.speech().generate(options)\n} catch (e) {\n  if (e instanceof Error && e.message === 'Invalid request body') {\n    // ensure the SDK client serializes a JSON string body\n  }\n}","preventionTips":["Use the provider's speech() API as the only entry point","Do not wrap the fetch with middleware that replaces or consumes the body","When invoking the fetch manually in tests, always pass JSON.stringify(options)"],"tags":["tts","request-body","validation"],"backgroundTag":"empty-required-field","analyzedSha":"f679616c34f1cf6d282c8d64264242af944b3fed","analyzedAt":"2026-09-08T13:18:15.005Z","contentChangedAt":"2026-09-08T13:18:15.005Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}