Skip to content

trtllm-build fails because an optimization profile has a minimum dimension above its optimum

TensorRT requires min to be less than or equal to opt, and opt less than or equal to max, for every dynamic dimension in an optimization profile. The engine build aborts when TensorRT-LLM derives a profile in which some dimension violates that ordering, usually because build flags imply a minimum larger than the optimum that was set.

Quick answer

Rebuild with TLLM_LOG_LEVEL=TRACE to print the per-tensor minimum, optimum and maximum table, find the row where minimum exceeds optimum, and correct the flag that set it. Removing an explicit --opt_num_tokens fixes most cases.

Environment#tensorrt-llm#trtllm-build#optimization-profile#engine-build#opt-num-tokens#inference-build

What this failure is

A build-time failure in which TensorRT-LLM rejects an optimization profile because some dynamic dimension was assigned a minimum larger than its optimum, violating the min less than or equal to opt less than or equal to max ordering TensorRT requires.

Why it happens (the mechanism)

TensorRT requires every dynamic dimension to satisfy min less than or equal to opt less than or equal to max, and validates it when a profile is evaluated. TensorRT-LLM runs the same check earlier so the message is legible. The ordering is violated when build flags are set independently: opt_num_tokens defaults to max_batch_size times max_beam_width, so pinning it by hand while other flags raise the derived minimum places opt underneath min for a batched dimension such as input_ids.

What you'll observe

  • trtllm-build aborts before an engine file is produced
  • The same flags built successfully against an earlier TensorRT-LLM version
  • The failing dimension is not named in the default build output, so there is nothing to correct
  • Removing one flag makes the build succeed without explaining which value was inconsistent

Common symptoms and what they mean

SymptomWhy it happens
[TRT-LLM] [E] Error building engine: optimization profile is invalid.TensorRT validates each optimization profile by checking that the maximum dimensions are at least the optimum, and the optimum at least the minimum. TensorRT-LLM runs the same check earlier, during its own pre-build pass, so that the message names the failure rather than surfacing a raw TensorRT assertion.
min dimension is greater than opt dimension for input_idsThe usual trigger is opt_num_tokens sitting below the minimum implied by other flags. It defaults to max_batch_size multiplied by max_beam_width, so setting it by hand while leaving those flags to grow can place opt underneath the derived min for a batched dimension such as input_ids.
Build aborts during profile validation, before any TensorRT kernel timing beginsWith --multiple_profiles the profile-splitting logic generates several min, opt and max tuples rather than one. A value that is consistent in the first profile can be inconsistent in another, which is why the build can fail while the flags look reasonable.

Which systems are affected

  • trtllm-build invocations that set --opt_num_tokens explicitly
  • Builds using --multiple_profiles, where a later profile can be invalid while profile 0 is fine
  • Configurations where max_seq_len is deduced from the model config and conflicts with an explicit max_input_len
  • Cross-version builds where a flag's default changed between TensorRT-LLM releases

How to confirm this is the problem

Apply the following checklist to a small reproduction: each box below is a positive signal that you are looking at this exact failure rather than a sibling in the same taxonomy.

  • Export TLLM_LOG_LEVEL=TRACE and re-run the build; the tensor shape table printed before compilation shows the minimum, optimum and maximum for each named dimension.
  • Compare the explicit values passed for opt_num_tokens, max_batch_size and max_beam_width; opt_num_tokens below max_batch_size multiplied by max_beam_width is the common inconsistency.
  • Rebuild with --multiple_profiles removed. A build that then succeeds confirms the invalid tuple was produced by profile splitting rather than by a single flag.

Example training logs (fingerprint)

training.log (synthetic fingerprint)
[TRT-LLM] [E] Error building engine: optimization profile is invalid.
[TRT-LLM] [E] min dimension is greater than opt dimension for input_ids
[TRT-LLM] [I] input_ids | Min (1) | Opt (8) | Max (8192)

Timestamps and exact values vary across runs, but the pattern. An info-level start, an early WARN, an ERROR carrying the symptom. Is the actual fingerprint you should alert on. The Denpex platform flags this combination automatically.

Root cause, fix & prevention, signed in

Sign up free to see why this failure really happens, the exact remediation steps, and the production-grade prevention pattern. You also get 3 free full diagnoses for your own training logs.

Sign up free. Unlock the full analysis

No credit card · 3 free diagnoses · Instant access

Why the recommended fix works

Letting opt_num_tokens return to its default restores the relationship it has with max_batch_size and max_beam_width, which is what the derived minimum is computed from. Printing the profile table replaces guesswork with the specific dimension name, so the flag that needs changing is identified rather than found by removing flags one at a time.

Code examples

typical reference pattern
// Typical pattern:
import torch.optim as optim
optimizer = optim.AdamW(model.parameters(), lr=3e-4)
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=num_training_steps)
for step in range(num_training_steps):
    optimizer.zero_grad()
    loss = model(batch)
    loss.backward()
    optimizer.step()
    scheduler.step()

Adapt the snippet to your framework. The same pattern holds for PyTorch Lightning, Hugging Face Trainer, DeepSpeed, Megatron-LM, and vLLM training wrappers. Where the wrapper exposes a config flag (for examplelr_scheduler_type in Trainer), prefer the flag over the imperative API to keep the schedule declarative and reproducible.

Best practices by model family

Model / StackRecommendationNotes
First failure of this kindTLLM_LOG_LEVEL=TRACE and read the shape tableNames the offending tensor and dimension instead of leaving you to bisect flags.
Explicit --opt_num_tokens setRemove it and let it defaultDefaults to max_batch_size times max_beam_width; the documentation notes the flag may be removed.
--multiple_profiles enabledDisable it to isolate the invalid tupleA later profile can be invalid while profile 0 is fine.
max_seq_len left unspecifiedSet it explicitly alongside max_input_lenIt is deduced from the model config and the deduced value can contradict an explicit max_input_len.

With the fix vs without the fix

DimensionWith the fixWithout the fix
Where the failure is caughtTensorRT-LLM's pre-build pass, with a readable messageA raw TensorRT profile assertion
Identifying the bad dimensionTRACE-level shape table naming each tensorRemoving build flags one at a time
Source of the inconsistencyUsually opt_num_tokens set below the derived minimumAssumed to be a TensorRT bug

Real engineering notes

With --multiple_profiles the splitting logic emits several min, opt and max tuples instead of one, and a value that is consistent in profile 0 can be inconsistent in a later profile. That is why a build can fail while every flag looks individually reasonable. Disable the option to find out whether profile generation is the source before changing any shape flag.

Visual fingerprint

The ordering TensorRT requires, and the violation
valid    input_ids   min 1   <=   opt 8    <=   max 8192
invalid  input_ids   min 16  >    opt 8         max 8192   <-- build aborts
TensorRT accepts a profile only when the minimum is at most the optimum and the optimum at most the maximum. In the failing case the derived minimum of 16 exceeds the optimum of 8 that opt_num_tokens pinned, so the profile is rejected before any kernel timing runs.

Root cause, fix & prevention

Frequently asked questions

Twelve targeted questions that engineers and on-call staff most commonly ask about this failure.

Which dimension is actually wrong?
The default build output does not say. Re-run with TLLM_LOG_LEVEL=TRACE, which prints every input tensor with minimum, optimum and maximum columns, and look for the row where the minimum exceeds the optimum.
The same command worked on an earlier version.
Defaults for the shape flags have changed across TensorRT-LLM releases. Set max_batch_size, max_input_len, max_seq_len and max_num_tokens together as one coherent set rather than relying on defaults.
Should I set --opt_num_tokens?
Usually not. It defaults to max_batch_size times max_beam_width, the documentation notes it may be removed, and pinning it below the derived minimum is the most common cause of this failure.
Why does disabling --multiple_profiles help?
It stops the profile-splitting logic from generating several min, opt and max tuples, so only one profile has to be consistent. If the build then succeeds, the invalid tuple came from splitting.

Don't just read the fix, diagnose your run

The encyclopedia tells you what went wrong. Denpex tells you what went wrong in YOUR training run. With your logs, your config, and your stack.