mudler/LocalAI · critical

[acestep-cpp] FATAL: failed to load DiT from %s\n

Error message

[acestep-cpp] FATAL: failed to load DiT from %s\n

What it means

acestep-cpp (Go-backed C++ music generation backend) fatal at model load: dit_ggml_load() on the DiT GGUF failed, so load_model returns 1 before text-encoder/VAE stages. dit_ggml_load logs its own reason (unopenable file, bad GGUF magic, unsupported tensor layout); this line is the outer summary. The process should be treated as unable to serve generation.

Source

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

    }
    fprintf(stderr, "[%-5s] ", level_str);
    fputs(log, stderr);
    fflush(stderr);
}

int load_model(const char * lm_model_path, const char * text_encoder_path,
               const char * dit_model_path, const char * vae_model_path) {
    ggml_log_set(ggml_log_cb, nullptr);
    ggml_backend_load_all();

    g_lm_path       = lm_model_path;
    g_text_enc_path = text_encoder_path;
    g_dit_path      = dit_model_path;

    // Load DiT model (backend init + config are handled inside dit_ggml_load)
    fprintf(stderr, "[acestep-cpp] Loading DiT from %s\n", dit_model_path);
    if (!dit_ggml_load(&g_dit, dit_model_path)) {
        fprintf(stderr, "[acestep-cpp] FATAL: failed to load DiT from %s\n", dit_model_path);
        return 1;
    }
    g_dit_loaded = true;

    // Read DiT GGUF metadata + silence_latent
    {
        GGUFModel gf = {};
        if (gf_load(&gf, dit_model_path)) {
            g_is_turbo           = gf_get_bool(gf, "acestep.is_turbo");
            const void * sl_data = gf_get_data(gf, "silence_latent");
            if (sl_data) {
                g_silence_full.resize(15000 * 64);
                memcpy(g_silence_full.data(), sl_data, 15000 * 64 * sizeof(float));
                fprintf(stderr, "[acestep-cpp] silence_latent: [15000, 64] loaded\n");
            } else {
                fprintf(stderr, "[acestep-cpp] FATAL: silence_latent not found in %s\n", dit_model_path);
                gf_close(&gf);
                return 2;

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Check the dit_ggml_load log line above for the precise cause (I/O vs format).
  2. Confirm dit_model_path points at the DiT file specifically and the file is complete (compare size/checksum with the gallery entry).
  3. Keep the matched set of DiT/text-encoder/VAE GGUFs from one conversion; re-download from the model gallery if in doubt.
  4. Verify argument order of load_model(lm, text_encoder, dit, vae) at the call site.

Example fix

// before: paths transposed
load_model(lm, dit_path, text_enc_path, vae_path);

// after
load_model(lm_path, text_enc_path, dit_path, vae_path);
Defensive patterns

Strategy: validation

Validate before calling

// validate the DiT GGUF before load_model
bool dit_gguf_ok(const char *path) {
    GGUFModel gf;
    if (!gf_load(&gf, path)) return false;
    bool ok = gf_get_data(gf, "silence_latent") != nullptr;
    gf_close(&gf);
    return ok;
}
if (!dit_gguf_ok(dit_path)) return fmt.Errorf("DiT GGUF unusable: %s", dit_path);

Prevention

When it happens

Trigger: Calling load_model with a dit_model_path that is missing, truncated mid-download, not actually the DiT GGUF (paths swapped with VAE/text-encoder files), or a DiT file from an incompatible conversion; dit_ggml_load returns false.

Common situations: Wrong path order in the four-argument load call; partial downloads; mixing GGUFs from different acestep conversion revisions; moving model dirs after configuration.

Related errors


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