mudler/LocalAI · critical

[acestep-cpp] FATAL: failed to load BPE tokenizer\n

Error message

[acestep-cpp] FATAL: failed to load BPE tokenizer\n

What it means

acestep-cpp fatal during generation setup: load_bpe_from_gguf() on the text-encoder GGUF failed, so prompts cannot be tokenized; generate_music returns 3. It means the text-encoder file is missing/unreadable, not a GGUF, or lacks the tokenizer (vocab/merges) metadata this loader expects.

Source

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

    // Compute T (latent frames at 25Hz)
    int T = (int)(duration * FRAMES_PER_SECOND);
    T     = ((T + g_dit.cfg.patch_size - 1) / g_dit.cfg.patch_size) * g_dit.cfg.patch_size;
    int S = T / g_dit.cfg.patch_size;

    if (T > 15000) {
        fprintf(stderr, "[acestep-cpp] ERROR: T=%d exceeds max 15000\n", T);
        return 2;
    }

    int Oc     = g_dit.cfg.out_channels;      // 64
    int ctx_ch = g_dit.cfg.in_channels - Oc;  // 128

    fprintf(stderr, "[acestep-cpp] T=%d, S=%d, duration=%.1fs, seed=%d\n", T, S, duration, seed);

    // 1. Load BPE tokenizer from text encoder GGUF
    BPETokenizer tok;
    if (!load_bpe_from_gguf(&tok, g_text_enc_path.c_str())) {
        fprintf(stderr, "[acestep-cpp] FATAL: failed to load BPE tokenizer\n");
        return 3;
    }

    // 2. Build formatted prompts (matches dit-vae.cpp text2music template)
    std::string instruction = "Fill the audio semantic mask based on the given conditions:";

    char metas[512];
    snprintf(metas, sizeof(metas),
             "- bpm: %s\n- timesignature: %s\n- keyscale: %s\n- duration: %d seconds\n",
             bpm_str, ts_str.c_str(), ks_str.c_str(), (int)duration);

    std::string text_str  = std::string("# Instruction\n") + instruction + "\n\n" +
                            "# Caption\n" + cap_str + "\n\n" +
                            "# Metas\n" + metas + "<|endoftext|>\n";
    std::string lyric_str = std::string("# Languages\n") + lang_str + "\n\n# Lyric\n" +
                            lyrics_str + "<|endoftext|>";

    // 3. Tokenize

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Verify g_text_enc_path exists and is the text-encoder GGUF from the same matched artifact set as the DiT.
  2. Inspect it for tokenizer keys (gguf-dump | grep -i 'tokenizer\|vocab\|merge') and re-download/re-convert with the documented converter if absent.
  3. Check load_model stored the intended path — argument order matters (lm, text_encoder, dit, vae).

Example fix

# before: tokenizer tensors missing
gguf-dump text_enc.gguf | grep -c tokenizer   # 0 -> FATAL at generate

# after: re-export with converter that embeds BPE
gguf-dump text_enc.gguf | grep -c tokenizer   # >0 -> tokenizes ok
Defensive patterns

Strategy: validation

Validate before calling

# verify tokenizer tensors exist in the text-encoder GGUF before deploy
gguf-dump text_enc.gguf | grep -qi 'tokenizer' || { echo 'text_enc.gguf lacks BPE data' >&2; exit 1; }
[ -f "$TEXT_ENC" ] || { echo 'text encoder missing' >&2; exit 1; }

Type guard

bool text_encoder_has_bpe(const char *path) {
    BPETokenizer tok;
    bool ok = load_bpe_from_gguf(&tok, path);
    if (ok) bpe_tokenizer_free(&tok);
    return ok;
}

Prevention

When it happens

Trigger: load_model succeeded for DiT/VAE but generate_music is called with g_text_enc_path pointing at a missing file, a non-GGUF, or a text-encoder GGUF converted without embedded BPE vocab/merges; load_bpe_from_gguf returns false.

Common situations: Text-encoder artifact forgotten in deployment (only DiT+VAE copied); community conversions stripping tokenizer tensors; path typos for the second of four model paths; mismatched converter revision.

Related errors


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