calesthio/OpenMontage · error · ValueError
safety_identifier must be at most 64 characters
Error message
safety_identifier must be at most 64 characters
What it means
Raised by SeedanceArkVideo._validate_optional_parameters when the optional 'safety_identifier' string exceeds 64 characters. Ark uses safety_identifier to attribute generations to an end user for abuse tracking, and enforces a 64-character ceiling. The check is client-side, so it fires before any request is sent.
Source
Thrown at tools/video/seedance_ark.py:1219
f"{label} must be a public/signed URL or asset:// ID; "
"Ark does not document video Base64 or local paths"
)
def _validate_optional_parameters(self, payload: dict[str, Any]) -> None:
callback = payload.get("callback_url")
if callback is not None and not str(callback).startswith(
("https://", "http://")
):
raise ValueError("callback_url must be an http(s) URL")
expires = payload.get("execution_expires_after")
if expires is not None and not 3600 <= int(expires) <= 259200:
raise ValueError("execution_expires_after must be between 3600 and 259200")
priority = payload.get("priority")
if priority is not None and not 0 <= int(priority) <= 9:
raise ValueError("priority must be between 0 and 9")
safety = payload.get("safety_identifier")
if safety is not None and len(str(safety)) > 64:
raise ValueError("safety_identifier must be at most 64 characters")
def _validate_request_size(self, payload: dict[str, Any]) -> None:
# Base64 dominates request size; summing encoded media is a conservative
# lower-cost check that avoids building a second complete JSON string.
encoded_bytes = 0
for item in payload["content"]:
media = (
item.get("image_url")
or item.get("audio_url")
or item.get("video_url")
or {}
)
url = str(media.get("url", ""))
if url.startswith("data:"):
encoded_bytes += len(url.encode("ascii"))
if encoded_bytes >= self.MAX_REQUEST_BYTES:
raise ValueError("Ark request body must be smaller than 64 MB")
View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Pass a short stable identifier such as a user id, truncated hash, or UUID (36 chars).
- If you need longer attribution data, hash it first (e.g. sha256 hexdigest truncated to 64) or store the mapping server-side.
- Omit the key if you do not need per-user attribution.
Example fix
# before
inputs = {"safety_identifier": f"tenant={tenant}:user={email}:session={sid}"}
# after
import hashlib
inputs = {"safety_identifier": hashlib.sha256(email.encode()).hexdigest()[:32]} Defensive patterns
Strategy: validation
Validate before calling
sid = inputs.get("safety_identifier")
if sid is not None and len(str(sid)) > 64:
import hashlib
inputs["safety_identifier"] = hashlib.sha256(str(sid).encode()).hexdigest()[:32] Type guard
def is_valid_safety_identifier(v) -> bool:
return v is None or len(str(v)) <= 64 Prevention
- Pass opaque short ids (user id / UUID) as safety_identifier, never composite strings.
- Hash long identifiers before sending.
When it happens
Trigger: Passing safety_identifier as a long free-form label, a concatenated user+session string, a UUID with a namespace prefix, or a JSON blob instead of a short user identifier.
Common situations: Developers embedding emails, composite keys, or serialized metadata into safety_identifier; or hashing schemes that emit long hex digests.
Related errors
- priority must be between 0 and 9
- text_to_video does not accept reference media; use image_to_
- image_to_video requires exactly one reference image
- provide only one of end_image_url/end_image_path
- reference_to_video accepts at most {max_images} reference im
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/3aa85bf7bdf438c7.
Report an issue: GitHub.