1Panel-dev/1Panel · warning · Error

aiTools.agents.allowedOriginsInvalid

Error message

aiTools.agents.allowedOriginsInvalid

What it means

normalizeAllowedOrigin (frontend/src/utils/agent.ts:57) rejects an empty/whitespace-only allowed-origin entry. The function is the single validator for the AI-agent allowed-origins textarea; every line fed through parseAllowedOriginInput must be a bare http(s) origin. This branch fires before URL parsing, so '' or ' ' input reaches it directly.

Source

Thrown at frontend/src/utils/agent.ts:57

};

export const getOpenclawAccessScheme = (version: string): 'http' | 'https' => {
    return isOpenclawHTTPSWindowVersion(version) ? 'https' : 'http';
};

export const buildDefaultAllowedOrigin = (systemIP: string, port?: number | string, version?: string): string => {
    const target = String(systemIP || '').trim() || openclawDefaultAccessHost;
    if (!port) {
        return '';
    }
    const host = target.includes(':') && !target.startsWith('[') && !target.endsWith(']') ? `[${target}]` : target;
    return `${getOpenclawAccessScheme(String(version || ''))}://${host}:${port}`;
};

export const normalizeAllowedOrigin = (value: string): string => {
    const target = String(value || '').trim();
    if (!target) {
        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));
    }
    let parsed: URL;
    try {
        parsed = new URL(target);
    } catch (error) {
        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));
    }
    if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));
    }
    if (parsed.username || parsed.password || parsed.search || parsed.hash) {
        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));
    }
    if (parsed.pathname && parsed.pathname !== '/') {
        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));
    }
    if (!parsed.host) {
        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));

View on GitHub (pinned to 5ac7c80881)

Solutions

  1. Trim the whole textarea value and skip empty lines before validating (parseAllowedOriginInput already skips truly empty lines — make sure values reach it trimmed)
  2. Remove blank/whitespace-only lines from the input and resubmit
  3. If calling normalizeAllowedOrigin directly, guard empty input with a form-level required rule so the user gets a field error instead of a thrown Error

Example fix

// before
const origins = raw.split('\n').map(normalizeAllowedOrigin);
// after
const origins = raw.split(/\r?\n/).map(l => l.trim()).filter(Boolean).map(normalizeAllowedOrigin);
Defensive patterns

Strategy: validation

Validate before calling

const lines = (raw || '').split(/\r?\n/).map(l => l.trim()).filter(Boolean);
if (!lines.length) { /* field-level 'at least one origin required' error */ }

Type guard

const isNonEmptyOriginInput = (v: string): boolean => String(v ?? '').trim().length > 0;

Try / catch

// in the form submit handler
try { parseAllowedOriginsInput(textarea); }
catch (e) { setFieldError('allowedOrigins', t('aiTools.agents.allowedOriginsInvalid')); return; }

Prevention

When it happens

Trigger: parseAllowedOriginInput called on textarea content where a line contains only whitespace after trim (blank-with-spaces lines), or normalizeAllowedOrigin invoked programmatically with '' / undefined coerced by String(value||'').

Common situations: User pastes origins separated by extra blank lines containing spaces; trailing whitespace line at the end of the textarea; a caller passes an unset form field.

Related errors


AI-assisted analysis of 1Panel-dev/1Panel@5ac7c80881 (2026-08-15). Data as JSON: /api/errors/018b1563354a832f. Report an issue: GitHub.