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

  1. Truncate the title to 80 characters or fewer before calling the tool.
  2. 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

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


AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12). Data as JSON: /api/errors/c531502c786369d9. Report an issue: GitHub.