Comfy-Org/ComfyUI · error · TypeError

Unexpected type for duration key, must be str, int or float

Error message

Unexpected type for duration key, must be str, int or float

What it means

In comfy/text_encoders/ace15.py, _metas_to_cap builds a metadata caption for the ACE 1.5 music model. The `duration` kwarg is normalized to 'N/A' if absent, formatted when str/int/float, but any other Python type (None, list, dict, bool is technically int but e.g. None) hits the else branch and raises TypeError.

Source

Thrown at comfy/text_encoders/ace15.py:177

        if len(user_metas):
            meta_yaml = yaml.dump(user_metas, allow_unicode=True, sort_keys=True).strip()
        else:
            meta_yaml = ""
        return f"<think>\n{meta_yaml}\n</think>" if not return_yaml else meta_yaml

    def _metas_to_cap(self, **kwargs) -> str:
        use_keys = ("bpm", "timesignature", "keyscale", "duration")
        user_metas = { k: kwargs.pop(k, "N/A") for k in use_keys }
        timesignature = user_metas.get("timesignature")
        if isinstance(timesignature, str) and timesignature.endswith("/4"):
            user_metas["timesignature"] = timesignature[:-2]
        duration = user_metas["duration"]
        if duration == "N/A":
            user_metas["duration"] = "30 seconds"
        elif isinstance(duration, (str, int, float)):
            user_metas["duration"] = f"{math.ceil(float(duration))} seconds"
        else:
            raise TypeError("Unexpected type for duration key, must be str, int or float")
        return "\n".join(f"- {k}: {user_metas[k]}" for k in use_keys)

    def tokenize_with_weights(self, text, return_word_ids=False, **kwargs):
        text = text.strip()
        text_negative = kwargs.get("caption_negative", text).strip()
        lyrics = kwargs.get("lyrics", "")
        lyrics_negative = kwargs.get("lyrics_negative", lyrics)
        duration = kwargs.get("duration", 120)
        if isinstance(duration, str):
            duration = float(duration.split(None, 1)[0])
        language = kwargs.get("language")
        seed = kwargs.get("seed", 0)

        generate_audio_codes = kwargs.get("generate_audio_codes", True)
        cfg_scale = kwargs.get("cfg_scale", 2.0)
        temperature = kwargs.get("temperature", 0.85)
        top_p = kwargs.get("top_p", 0.9)
        top_k = kwargs.get("top_k", 0.0)

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Pass duration as a number or numeric string (e.g. 120 or '90'); let the tokenizer default (120) apply by omitting it entirely.
  2. Normalize before the call: duration = float(duration) if duration is not None else 120.
  3. In API payloads, drop the duration key rather than sending null.

Example fix

# before
tokens = tokenizer.tokenize_with_weights(prompt, duration=None)  # TypeError

# after
duration = 120 if duration is None else duration
tokens = tokenizer.tokenize_with_weights(prompt, duration=duration)
Defensive patterns

Strategy: type-guard

Validate before calling

if duration is not None and not isinstance(duration, (str, int, float)):
    raise TypeError('duration must be str, int, or float')
duration = 120 if duration is None else duration

Type guard

def is_valid_duration(d) -> bool:
    return d is None or isinstance(d, (str, int, float)) and not isinstance(d, bool)

Try / catch

try:
    tokens = tokenizer.tokenize_with_weights(prompt, duration=duration)
except TypeError as e:
    if 'duration' in str(e):
        tokens = tokenizer.tokenize_with_weights(prompt, duration=120)
    else:
        raise

Prevention

When it happens

Trigger: Calling tokenize_with_weights(..., duration=None) or passing duration as a list/dict/tuple from a node or API payload; JSON workflow params deserialized into a non-numeric duration; downstream code that forwards raw widget values without type coercion.

Common situations: API clients sending "duration": null in JSON (becomes None in Python); custom nodes passing unvalidated widget structs; workflows where the duration widget is optional and yields None instead of the default.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/47136ada40141b5c. Report an issue: GitHub.