{"record":{"id":"018b1563354a832f","repo":"1Panel-dev/1Panel","slug":"aitools-agents-allowedoriginsinvalid","errorCode":null,"errorMessage":"aiTools.agents.allowedOriginsInvalid","messagePattern":"aiTools\\.agents\\.allowedOriginsInvalid","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"frontend/src/utils/agent.ts","lineNumber":57,"sourceCode":"};\n\nexport const getOpenclawAccessScheme = (version: string): 'http' | 'https' => {\n    return isOpenclawHTTPSWindowVersion(version) ? 'https' : 'http';\n};\n\nexport const buildDefaultAllowedOrigin = (systemIP: string, port?: number | string, version?: string): string => {\n    const target = String(systemIP || '').trim() || openclawDefaultAccessHost;\n    if (!port) {\n        return '';\n    }\n    const host = target.includes(':') && !target.startsWith('[') && !target.endsWith(']') ? `[${target}]` : target;\n    return `${getOpenclawAccessScheme(String(version || ''))}://${host}:${port}`;\n};\n\nexport const normalizeAllowedOrigin = (value: string): string => {\n    const target = String(value || '').trim();\n    if (!target) {\n        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));\n    }\n    let parsed: URL;\n    try {\n        parsed = new URL(target);\n    } catch (error) {\n        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));\n    }\n    if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));\n    }\n    if (parsed.username || parsed.password || parsed.search || parsed.hash) {\n        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));\n    }\n    if (parsed.pathname && parsed.pathname !== '/') {\n        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));\n    }\n    if (!parsed.host) {\n        throw new Error(i18n.global.t('aiTools.agents.allowedOriginsInvalid'));","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/1Panel-dev/1Panel/blob/5ac7c808815b0691009cd390414f03471312262f/frontend/src/utils/agent.ts#L39-L75","documentation":"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.","triggerScenarios":"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||'').","commonSituations":"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.","solutions":["Trim the whole textarea value and skip empty lines before validating (parseAllowedOriginInput already skips truly empty lines — make sure values reach it trimmed)","Remove blank/whitespace-only lines from the input and resubmit","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"],"exampleFix":"// before\nconst origins = raw.split('\\n').map(normalizeAllowedOrigin);\n// after\nconst origins = raw.split(/\\r?\\n/).map(l => l.trim()).filter(Boolean).map(normalizeAllowedOrigin);","handlingStrategy":"validation","validationCode":"const lines = (raw || '').split(/\\r?\\n/).map(l => l.trim()).filter(Boolean);\nif (!lines.length) { /* field-level 'at least one origin required' error */ }","typeGuard":"const isNonEmptyOriginInput = (v: string): boolean => String(v ?? '').trim().length > 0;","tryCatchPattern":"// in the form submit handler\ntry { parseAllowedOriginsInput(textarea); }\ncatch (e) { setFieldError('allowedOrigins', t('aiTools.agents.allowedOriginsInvalid')); return; }","preventionTips":["Trim and filter blank lines before validation","Mark the textarea required so emptiness fails form validation, not the parser"],"tags":["frontend","validation","agent-origins"],"backgroundTag":null,"analyzedSha":"5ac7c808815b0691009cd390414f03471312262f","analyzedAt":"2026-08-15T14:02:06.953Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}