{"record":{"id":"c57c130c32a8b6c0","repo":"jdx/mise","slug":"formula-has-no-stable-url","errorCode":null,"errorMessage":"formula has no stable URL","messagePattern":"formula has no stable URL","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/tap_formula_metadata.rb","lineNumber":217,"sourceCode":"    def head(*) = nil\n    def livecheck(*) = nil\n    def service(*) = nil\n    def test(*) = nil\n    def method_missing(*) = nil\n    def respond_to_missing?(*) = true\n  end\nend\n\ndef inferred_version(url)\n  basename = File.basename(url.to_s).sub(/\\.(tar\\.(gz|xz|bz2|zst)|tgz|txz|zip|gz)\\z/i, \"\")\n  match = basename.match(/(?:^|[-_v])([0-9]+(?:\\.[0-9A-Za-z]+)+(?:[-_.][0-9A-Za-z]+)*)/)\n  match && match[1]\nend\n\neval(STDIN.read.force_encoding(\"UTF-8\"), TOPLEVEL_BINDING, FORMULA_FILE, 1)\nklass = Formula.instance_variable_get(:@subclass)\nraise \"no Formula subclass found\" unless klass\nraise \"formula has no stable URL\" if klass.source_url.to_s.empty?\nraise \"formula has no stable sha256\" if klass.source_sha256.to_s.empty?\nversion = (klass.explicit_version || inferred_version(klass.source_url)).to_s\nraise \"could not infer formula version; add an explicit version declaration\" if version.to_s.empty?\n\nmetadata = {\n  \"name\" => FORMULA_NAME,\n  \"tap\" => ENV.fetch(\"MISE_BREW_TAP\"),\n  \"versions\" => { \"stable\" => version },\n  \"revision\" => klass.revision_value || 0,\n  \"keg_only\" => klass.keg_only_value || false,\n  \"dependencies\" => klass.runtime_dependencies || [],\n  \"build_dependencies\" => klass.build_dependencies || [],\n  \"bottle\" => {},\n  \"urls\" => { \"stable\" => { \"url\" => klass.source_url, \"checksum\" => klass.source_sha256 } },\n  \"ruby_source_path\" => ENV.fetch(\"MISE_BREW_SOURCE_PATH\"),\n  \"ruby_source_checksum\" => { \"sha256\" => ENV.fetch(\"MISE_BREW_SOURCE_CHECKSUM\") },\n  \"tap_git_head\" => ENV.fetch(\"MISE_BREW_TAP_COMMIT\")\n}","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/tap_formula_metadata.rb#L199-L235","documentation":"After eval'ing the formula file, mise checks that the Formula subclass recorded a stable source URL via the `url ...` DSL call. If the subclass never called `url` (or called it with nil), `klass.source_url` is nil and this raise fires. mise builds third-party formulas from source, so it requires a resolvable stable download URL.","triggerScenarios":"The formula declares its source only in a block the extractor skipped (e.g. only inside `head`, a `resource`, or a conditional `on_macos`/`on_arm` block that didn't run on the host), uses a DSL construct the stub swallows via `method_missing` (which returns nil and discards the url), or simply omits `url` in `stable`.","commonSituations":"Formulas relying on Homebrew features this lightweight stub does not model (e.g. urls set through custom DSL or strategies inside unexecuted conditionals); formulas with only `head` specs and no stable URL; formulas using url only inside `deprecate!`/disabled paths; a formula whose stable block calls url on a platform branch that doesn't match the host.","solutions":["Ensure the formula has a top-level `url \"https://...\"` inside `stable` (or class body) that executes unconditionally","If the url is inside a conditional block (on_macos/on_arm/on_system), confirm the host env vars (MISE_BREW_OS, arch) match so the branch executes, or move the url out of the conditional","Update the stub extractor if the formula uses an unrecognized DSL method that swallows the url call","Pin/modify the formula to a version with a plain stable url declaration"],"exampleFix":"// before\n//   class Foo < Formula\n//     head \"https://example.com/foo.git\"  # no stable url\n//   end\n// after\n//   class Foo < Formula\n//     url \"https://example.com/foo-1.2.3.tar.gz\"\n//     sha256 \"abc123...\"\n//     head \"https://example.com/foo.git\"\n//   end","handlingStrategy":"validation","validationCode":"body = File.read(formula_path)\nraise \"formula lacks a stable url declaration\" unless body.match?(/^\\s*url\\s+[\"']https?:\\/\\//)","typeGuard":"def has_stable_url?(formula_source)\n  formula_source.match?(/^\\s*url\\s+[\"'][^\"']+[\"']/)\nend","tryCatchPattern":"begin\n  extract_formula_metadata(formula_path)\nrescue RuntimeError => e\n  raise unless e.message == \"formula has no stable URL\"\n  warn \"Formula has no stable url; it is likely head-only or uses unsupported DSL\"\nend","preventionTips":["Only use formulas that declare a top-level stable `url`","Prefer formulas over head-only ones for source builds","Keep MISE_BREW_OS/arch env vars correct so conditional url blocks execute","Avoid formulas relying on Homebrew DSL features the lightweight stub swallows"],"tags":["homebrew","formula","missing-url","source"],"backgroundTag":"missing-required-config-field","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}