{"record":{"id":"3ebb89b3d313e8a6","repo":"can1357/oh-my-pi","slug":"the-configured-endpoint-is-not-a-valid-url","errorCode":null,"errorMessage":"the configured endpoint is not a valid URL","messagePattern":"the configured endpoint is not a valid URL","errorType":"validation","errorClass":"LegacyDestinationError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/uploaders-legacy.ts","lineNumber":70,"sourceCode":"\treadonly extraInfo: string;\n}\n\nfunction failure(destination: BlobDestinationId, error: unknown): Error {\n\tif (error instanceof DestinationUnavailableError || error instanceof LegacyDestinationError) return error;\n\tconst message = error instanceof Error ? error.message : String(error);\n\treturn new LegacyDestinationError(destination, message, error);\n}\n\nfunction configuredEndpoint(destination: BlobDestinationId, config: DestinationRuntimeConfig): URL {\n\tconst raw = optionString(config, \"endpoint\")?.trim();\n\tif (!raw) {\n\t\tthrow new DestinationUnavailableError(destination, \"a user-supplied replacement endpoint is required\");\n\t}\n\tlet endpoint: URL;\n\ttry {\n\t\tendpoint = new URL(raw);\n\t} catch (error) {\n\t\tthrow new LegacyDestinationError(destination, \"the configured endpoint is not a valid URL\", error);\n\t}\n\tif (endpoint.protocol !== \"https:\" && endpoint.protocol !== \"http:\") {\n\t\tthrow new LegacyDestinationError(destination, \"the configured endpoint must use HTTP or HTTPS\");\n\t}\n\tconst hostname = endpoint.hostname.toLowerCase();\n\tconst blocked = BLOCKED_CUSTOM_HOSTS[destination];\n\tif (blocked) {\n\t\tfor (const domain of blocked) {\n\t\t\tif (hostname === domain || hostname.endsWith(`.${domain}`)) {\n\t\t\t\tthrow new DestinationUnavailableError(destination, \"the defunct public endpoint cannot be used\");\n\t\t\t}\n\t\t}\n\t}\n\treturn endpoint;\n}\n\nfunction sendSpaceEndpoint(config: DestinationRuntimeConfig): URL {\n\tconst endpoint = configuredEndpoint(\"sendspace\", config);","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/uploaders-legacy.ts#L52-L88","documentation":"This LegacyDestinationError is thrown when the user-configured `endpoint` option for a legacy blob destination (puush, mediafire, localhostr, lambda, lobfile, transfer-sh, sendspace, etc.) cannot be parsed by the URL constructor. The library requires a custom replacement endpoint because the original public services are defunct, and it validates the value with `new URL(raw)` before any network I/O. It wraps the underlying parse error as `cause`.","triggerScenarios":"Calling an uploader that resolves its endpoint via configuredEndpoint() (e.g. createLegacyUploader -> endpoint) with config.endpoint set to a string that fails `new URL()`: a bare hostname like 'example.com/upload' without a scheme, an empty-after-trim value is handled separately, typos like 'https//...', or values with spaces/invalid characters.","commonSituations":"Users copy a replacement endpoint from documentation and omit the `https://` scheme; environment variables or YAML config with trailing whitespace/quotes left in the value; template expansion producing 'undefined' or placeholder text in the endpoint string.","solutions":["Prefix the endpoint with an explicit scheme, e.g. change 'files.example.com/upload' to 'https://files.example.com/upload'","Trim quotes, whitespace, and template remnants from the configured endpoint value","Validate the string with `new URL(value)` before saving it to configuration","Check the wrapped `cause` property of the error for the exact WHATWG URL parse failure"],"exampleFix":"// before\nendpoint: files.example.com/upload\n// after\nendpoint: https://files.example.com/upload","handlingStrategy":"validation","validationCode":"function isValidHttpUrl(value) {\n  try {\n    const u = new URL(String(value).trim());\n    return u.protocol === \"https:\" || u.protocol === \"http:\";\n  } catch {\n    return false;\n  }\n}\nif (!isValidHttpUrl(config.endpoint)) throw new Error(\"endpoint must be an absolute http(s) URL\");","typeGuard":"function isHttpUrl(value: unknown): value is URL {\n  try {\n    const u = new URL(String(value));\n    return u.protocol === \"https:\" || u.protocol === \"http:\";\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":"try {\n  await uploader.upload(request);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"not a valid URL\")) {\n    // fix config.endpoint: add scheme, trim junk\n  } else throw err;\n}","preventionTips":["Always include an explicit https:// scheme in endpoint config values","Trim surrounding whitespace and quotes before storing the endpoint","Validate the endpoint with new URL() at config-load time, not upload time","Keep endpoints in typed config with a parse-time assertion"],"tags":["configuration","url-parsing","upload"],"backgroundTag":"invalid-url-config","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}