{"record":{"id":"1cefe1a2532bba2f","repo":"glanceapp/glance","slug":"parsing-url-v-1cefe1","errorCode":null,"errorMessage":"parsing URL: %v","messagePattern":"parsing URL: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget-iframe.go","lineNumber":27,"sourceCode":"\nvar iframeWidgetTemplate = mustParseTemplate(\"iframe.html\", \"widget-base.html\")\n\ntype iframeWidget struct {\n\twidgetBase `yaml:\",inline\"`\n\tcachedHTML template.HTML `yaml:\"-\"`\n\tSource     string        `yaml:\"source\"`\n\tHeight     int           `yaml:\"height\"`\n}\n\nfunc (widget *iframeWidget) initialize() error {\n\twidget.withTitle(\"IFrame\").withError(nil)\n\n\tif widget.Source == \"\" {\n\t\treturn errors.New(\"source is required\")\n\t}\n\n\tif _, err := url.Parse(widget.Source); err != nil {\n\t\treturn fmt.Errorf(\"parsing URL: %v\", err)\n\t}\n\n\tif widget.Height == 50 {\n\t\twidget.Height = 300\n\t} else if widget.Height < 50 {\n\t\twidget.Height = 50\n\t}\n\n\twidget.cachedHTML = widget.renderTemplate(widget, iframeWidgetTemplate)\n\n\treturn nil\n}\n\nfunc (widget *iframeWidget) Render() template.HTML {\n\treturn widget.cachedHTML\n}\n","sourceCodeStart":9,"sourceCodeEnd":44,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-iframe.go#L9-L44","documentation":"iframe widget initialization failed because url.Parse rejected the configured source. As with other URL validation errors, url.Parse only fails on control characters or malformed percent-escapes; a missing scheme passes here but produces a broken iframe at render time.","triggerScenarios":"source: contains control characters, invalid escape sequences like '%zz', or unquoted YAML that gets mangled.","commonSituations":"Copy-paste artifacts in the source field; URLs with query strings containing raw % characters; YAML special-character issues.","solutions":["Rewrite and quote the source: value","Percent-encode stray % characters (%25)","Include https:// so the iframe actually loads after validation passes"],"exampleFix":"# before\n- type: iframe\n  source: example.com/embed%zz\n# after\n- type: iframe\n  source: \"https://example.com/embed\"","handlingStrategy":"validation","validationCode":"u, err := url.Parse(widget.Source)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"iframe source %q must be an absolute http(s) URL\", widget.Source)\n}","typeGuard":"func isAbsoluteHTTPSource(s string) bool {\n    u, err := url.Parse(s)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"\n}","tryCatchPattern":"if err := widget.initialize(); err != nil {\n    widget.withError(err) // show config error in the panel instead of failing the page\n}","preventionTips":["Always give iframe sources a full https:// URL","Only embed sources that send X-Frame-Options: SAMEORIGIN-free / frame-ancestors allowing your origin — parse errors aside, framing fails silently otherwise"],"tags":["iframe","url","yaml","validation"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}