Budibase/budibase · error · Error
Invalid Github URL
Error message
Invalid Github URL
What it means
parseGithubUrl validates that a plugin source URL is a well-formed URL. If new URL(url) throws (malformed URL), the function throws "Invalid Github URL". A subsequent check rejects non-https/non-github hosts with a different message, so this error is purely about URL parse failure.
Source
Thrown at packages/server/src/api/controllers/plugin/github.ts:13
import { utils as coreUtils } from "@budibase/backend-core"
import {
deleteFolderFileSystem,
getPluginMetadata,
} from "../../../utilities/fileSystem"
import { downloadUnzipTarball } from "./utils"
function parseGithubUrl(url: string): URL {
let parsed: URL
try {
parsed = new URL(url)
} catch {
throw new Error("Invalid Github URL")
}
if (parsed.protocol !== "https:" || parsed.hostname !== "github.com") {
throw new Error("The plugin origin must be from Github")
}
return parsed
}
export async function request(
url: string,
headers: Record<string, string> = {},
err: string
) {
const response = await coreUtils.fetchWithBlacklist(url, { headers })
if (response.status >= 300) {
const respErr = await response.text()
throw new Error(`Error: ${err} - ${respErr}`)View on GitHub (pinned to a81a902e9a)
Solutions
- Prefix the URL with the scheme: https://github.com/<owner>/<repo>
- Use the HTTPS clone URL, not SSH (git@github.com:...)
- Trim whitespace and stray characters from the pasted URL
- Validate with new URL(url) in the browser console before submitting
Example fix
// before
await api.post("/api/plugins/github", { url: "github.com/user/repo" })
// after
await api.post("/api/plugins/github", { url: "https://github.com/user/repo" }) Defensive patterns
Strategy: validation
Validate before calling
const u = new URL(url)
if (u.protocol !== "https:" || u.hostname !== "github.com") {
throw new Error(`URL must be https://github.com/... got ${url}`)
}
await api.post("/api/plugins/github", { url: u.toString() })
Type guard
const isGithubUrl = (url: string): boolean => {
try { const u = new URL(url); return u.protocol === "https:" && u.hostname === "github.com" }
catch { return false }
}
Try / catch
try {
await api.post("/api/plugins/github", { url })
} catch (err) {
if (err.message === "Invalid Github URL") {
console.error(`Malformed URL "${url}" — use https://github.com/<owner>/<repo>`)
} else { throw err }
}
Prevention
- Always paste full HTTPS URLs including https:// scheme
- Use HTTPS GitHub URLs, not SSH (git@github.com:...) forms
- Trim whitespace from pasted URLs before submitting
- Pre-validate with new URL() in the client before calling the API
When it happens
Trigger: Calling the GitHub plugin upload endpoint with a URL that is not parseable — missing scheme ("github.com/user/repo"), spaces, typos, empty string, or a pasted SSH URL like git@github.com:user/repo.git.
Common situations: Pasting "github.com/budibase/plugins" without https:// into the builder's plugin import; copying SSH clone URLs instead of HTTPS; trailing garbage from copy/paste; relative paths submitted instead of absolute URLs.
Related errors
- The plugin origin must be from Github
- Invalid URL.
- Only HTTP(S) URLs are allowed.
- package.json is missing one of 'name', 'version' or 'descrip
- File is not valid - cannot upload.
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/8a04a60ca0c49723.
Report an issue: GitHub.