mudler/LocalAI · error

[moss-tts-cpp] ERROR: malloc(%zu) failed\n

Error message

[moss-tts-cpp] ERROR: malloc(%zu) failed\n

What it means

The malloc of n * sizeof(float) bytes for the PCM copy-out buffer failed (OOM at the C heap). Synthesis itself succeeded — engine pcm was produced — but the shim cannot hand a copy to the Go side, so it frees the engine buffer and returns nullptr. Indicates process address-space or memory exhaustion proportional to the generated audio length.

Source

Thrown at backend/go/moss-tts-cpp/cpp/mossttscpp.cpp:96

                          ? reference_wav
                          : nullptr;

    int n = 0, sr = 0;
    float *pcm = moss_local_tts(g_local, text, ref, seed, &n, &sr);
    if (!pcm || n <= 0) {
        fprintf(stderr, "[moss-tts-cpp] ERROR: moss_local_tts failed\n");
        if (pcm)
            moss_free(pcm);
        return nullptr;
    }

    // Copy into a plain malloc buffer the Go side frees via mtl_pcm_free, then
    // release the engine-owned buffer with moss_free (mirrors qwen3-tts-cpp,
    // keeping ownership on the C runtime's malloc/free).
    size_t bytes = (size_t)n * sizeof(float);
    float *buf = (float *)malloc(bytes);
    if (!buf) {
        fprintf(stderr, "[moss-tts-cpp] ERROR: malloc(%zu) failed\n", bytes);
        moss_free(pcm);
        return nullptr;
    }
    memcpy(buf, pcm, bytes);
    moss_free(pcm);

    if (out_n)
        *out_n = n;
    if (out_sr)
        *out_sr = sr;
    return buf;
}

void mtl_pcm_free(float *p) { free(p); }

void mtl_unload(void) {
    if (g_local) {
        moss_local_free(g_local);

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Reduce requested audio length or chunk long text into multiple shorter syntheses.
  2. Raise the container/process memory limit or free other loaded backends.
  3. Stream via chunked output if the engine supports it rather than one giant buffer.
  4. Check for leaked buffers on the Go side (mtl_pcm_free must be called on every returned pointer).
Defensive patterns

Strategy: validation

Validate before calling

// cap requested length before synthesis so the copy buffer stays bounded
const maxSamples = 48_000 * 300 // ~5 min
if estSamples(text) > maxSamples {
    return nil, errors.New("requested audio too long; chunk the text")
}

Prevention

When it happens

Trigger: Very long synthesis (huge n) on a process already near its memory ceiling; cgo/purego process with a fragmented heap; container memory limit hit at the moment of the copy.

Common situations: Generating long-form speech in a memory-capped container alongside resident model weights; 32-bit builds where address space runs out; repeated long generations fragmenting the heap.

Related errors


AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15). Data as JSON: /api/errors/2178175ecf05c547. Report an issue: GitHub.