mudler/LocalAI · critical

[acestep-cpp] ERROR: VAE decode failed\n

Error message

[acestep-cpp] ERROR: VAE decode failed\n

What it means

The final VAE decode stage failed: vae_ggml_decode_tiled() returned a negative sample count after the DiT diffusion run completed. Inputs to it are the DiT latent output (T frames), a stereo audio buffer sized 2*T*1920, and tile parameters 256/64. A negative return means the tiled decoder rejected the latent shape or the VAE (g_vae) was not in a state to decode. The shim aborts with exit code 6.

Source

Thrown at backend/go/acestep-cpp/cpp/goacestepcpp.cpp:268

    std::vector<float> noise(Oc * T);
    philox_randn((long long)seed, noise.data(), Oc * T, true);

    // 10. DiT generate
    std::vector<float> output(Oc * T);
    fprintf(stderr, "[acestep-cpp] DiT generate: T=%d, steps=%d, guidance=%.1f\n", T, num_steps, guidance_scale);

    dit_ggml_generate(&g_dit, noise.data(), context.data(), enc_hidden.data(), enc_S,
                      T, 1, num_steps, schedule.data(), output.data(), guidance_scale,
                      nullptr, nullptr, -1);
    fprintf(stderr, "[acestep-cpp] DiT generation done\n");

    // 11. VAE decode
    int                T_audio_max = T * 1920;
    std::vector<float> audio(2 * T_audio_max);

    int T_audio = vae_ggml_decode_tiled(&g_vae, output.data(), T, audio.data(), T_audio_max, 256, 64);
    if (T_audio < 0) {
        fprintf(stderr, "[acestep-cpp] ERROR: VAE decode failed\n");
        return 6;
    }
    fprintf(stderr, "[acestep-cpp] VAE decode done: %d samples (%.2fs @ 48kHz)\n", T_audio,
            (float)T_audio / 48000.0f);

    // 12. Peak normalization to -1.0 dB
    {
        float peak      = 0.0f;
        int   n_samples = 2 * T_audio;
        for (int i = 0; i < n_samples; i++) {
            float a = audio[i] < 0 ? -audio[i] : audio[i];
            if (a > peak) {
                peak = a;
            }
        }
        if (peak > 1e-6f) {
            const float target_amp = powf(10.0f, -1.0f / 20.0f);
            float       gain       = target_amp / peak;

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Check the preceding '[acestep-cpp] DiT generation done' line and the T value — clamp the requested duration so T stays within the VAE's supported range.
  2. Verify the VAE model path matches the same ACEStep release as the DiT (latent rate must agree with the 1920 samples-per-frame sizing in this code).
  3. Look at the ggml log lines immediately before the error for the specific tensor/shape failure inside vae_ggml_decode_tiled.
  4. Reduce concurrency / free other backends if the tiled decode is failing from buffer allocation.

Example fix

// before: duration longer than the VAE supports
T = requested_seconds * 16; // arbitrary large T
// after: clamp T to the VAE's supported latent-frame maximum
if (T > T_MAX) { fprintf(stderr, "clamping T %d -> %d\n", T, T_MAX); T = T_MAX; }
Defensive patterns

Strategy: validation

Validate before calling

// clamp requested duration so T stays within the VAE's latent-frame budget
const maxT = 2048 // VAE-specific limit
if t := secondsToLatentFrames(req.Duration); t > maxT {
    req.Duration = latentFramesToSeconds(maxT)
}

Prevention

When it happens

Trigger: Generating audio when the DiT produced a latent with unexpected T (e.g., T=0 or larger than the VAE's trained positional range), when g_vae was never loaded or was freed, when T_audio_max (T*1920) is smaller than what the tiled decode produces, or when the tile sizes 256/64 are incompatible with the VAE checkpoint.

Common situations: Requesting a duration that pushes T past the VAE's max latent frames; mismatched VAE checkpoint versus DiT checkpoint (different latent rate than 1920 samples/frame); memory exhaustion during tiled decode on CPU-only hosts.

Related errors


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