openclaw/openclaw · error · WidgetHtmlInputError
title must be 80 characters or fewer
Error message
title must be 80 characters or fewer
What it means
Thrown by the widget tool when the title param exceeds 80 characters. Discord Activity launch buttons and widget titles have a hard length cap; the Typebox schema (maxLength: 80) declares it statically, but this runtime WidgetHtmlInputError enforces it as a defense-in-depth check since raw params may bypass schema validation in some paths.
Source
Thrown at extensions/discord/src/activities/tool.ts:127
return {
label: variant.label,
name: variant.name,
description: variant.description,
parameters: variant.parameters,
execute: async (_toolCallId, rawParams) => {
const params = rawParams as Record<string, unknown>;
const html = readStringParam(params, variant.htmlParam, { required: true, trim: false });
const title = readStringParam(params, "title", { required: true });
const buttonLabel = readStringParam(params, "button_label") || "Open widget";
if (!html.trim()) {
throw new WidgetHtmlInputError(`${variant.htmlParam} is required`);
}
assertWidgetHtmlSize(html, DISCORD_WIDGET_HTML_MAX_BYTES, {
inputName: variant.htmlParam,
});
if (title.length > 80) {
throw new WidgetHtmlInputError("title must be 80 characters or fewer");
}
if (!buttonLabel.trim() || buttonLabel.length > 80) {
throw new WidgetHtmlInputError("button_label must be 1 to 80 characters");
}
const channelId = resolveDiscordChannelId(context);
if (!channelId) {
throw new WidgetHtmlInputError(
`${variant.name} requires a concrete Discord channel in the current session`,
);
}
// Persist before the button can be delivered so a launch never races an absent record;
// roll the record back if the post fails so a failed send leaves no unreachable widget.
const widgetId = await deps.runtime.store.createWidget({
html: buildDiscordWidgetDocument(title, html),
title,
channelId,
accountId: account.accountId,
createdAt: (deps.now ?? Date.now)(),View on GitHub (pinned to 01804a7531)
Solutions
- Truncate the title to 80 characters or fewer before calling the tool.
- If the title comes from user content, apply a truncation/ellipsis strategy upstream.
Example fix
// before
discord_widget({ html: '...', title: 'A'.repeat(90) }) // throws
// after
discord_widget({ html: '...', title: longTitle.slice(0, 80) }) Defensive patterns
Strategy: validation
Validate before calling
function clampTitle(title: string): string {
return title.length > 80 ? title.slice(0, 80) : title;
} Type guard
function isValidWidgetTitle(title: unknown): boolean {
return typeof title === 'string' && title.length >= 1 && title.length <= 80;
} Prevention
- Cap title length to 80 characters at the source.
- Apply truncation when titles come from dynamic content.
When it happens
Trigger: Passing a title longer than 80 characters; the model generates a verbose title; a dynamic title from user data exceeds the limit.
Common situations: Long descriptive titles generated without length awareness; concatenating dynamic segments that overflow.
Related errors
- button_label must be 1 to 80 characters
- ${variant.htmlParam} is required
- ${key} must be at most ${maxLength} characters
- Discord search requires query text. Provide query or content
- Discord channel target is required (use channel:<id>).
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/c531502c786369d9.
Report an issue: GitHub.