{"record":{"id":"c4682659bd1ab074","repo":"github/markup","slug":"the-symbol-symbol-is-already-defined","errorCode":null,"errorMessage":"The '#{symbol}' symbol is already defined.","messagePattern":"The '#(.+?)' symbol is already defined\\.","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/github/markup.rb","lineNumber":67,"sourceCode":"\n    def render_s(symbol, content, options: {})\n      raise ArgumentError, 'Can not render a nil.' if content.nil?\n\n      if markups.key?(symbol)\n        markups[symbol].render(nil, content, options: options)\n      else\n        content\n      end\n    end\n\n    def markup(symbol, gem_name, regexp, languages, opts = {}, &block)\n      impl = GemImplementation.new(regexp, languages, gem_name, &block)\n      markup_impl(symbol, impl)\n    end\n\n    def markup_impl(symbol, impl)\n      if markups.key?(symbol)\n        raise ArgumentError, \"The '#{symbol}' symbol is already defined.\"\n      end\n      markups[symbol] = impl\n    end\n\n    def command(symbol, command, regexp, languages, name, &block)\n      if File.exist?(file = File.dirname(__FILE__) + \"/commands/#{command}\")\n        command = file\n      end\n\n      impl = CommandImplementation.new(regexp, languages, command, name, &block)\n      markup_impl(symbol, impl)\n    end\n\n    def can_render?(filename, content, symlink: false)\n      renderer(filename, content, symlink: symlink) != nil\n    end\n\n    def renderer(filename, content, symlink: false)","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/github/markup/blob/76e2682193828b98471b3a071edf4db0590ccacb/lib/github/markup.rb#L49-L85","documentation":"GitHub::Markup.markup_impl raises ArgumentError \"The '#{symbol}' symbol is already defined.\" when a renderer is registered under a symbol that already has an entry in the @@markups registry. The registry is populated when the gem is required (lib/github/markups registers :markdown, :rst, :asciidoc, etc.), and both markup() and command() funnel through markup_impl(), which refuses to overwrite an existing key. This protects the symbol -> implementation lookup used by render_s from silently replacing a renderer.","triggerScenarios":"Calling GitHub::Markup.markup(:markdown, ...) or GitHub::Markup.command(:rst, ...) for a symbol the default lib/github/markups file already registered; a custom markups registration file being loaded twice (double require, Rails dev reloading, autoload/eager-load overlap); two gems/initializers both registering the same symbol.","commonSituations":"An initializer that adds a custom renderer and gets re-evaluated on each Rails dev reload; copying the gem's own registration block and forgetting to change the symbol; a gem dependency that also registers renderers colliding with the app's; upgrading github-markup and not noticing a symbol your code reuses was added upstream.","solutions":["Register the custom renderer under a fresh, unused symbol (GitHub::Markup.markup(:myengine, 'myengine-gem', /myext\\z/, []).","Find and eliminate the double load: ensure the registration file is require'd once, or wrap it with `unless GitHub::Markup.markups.key?(:your_symbol)`.","If you intend to replace a built-in renderer, remove/monkey-patch the default registration in lib/github/markups rather than re-registering the same symbol.","Search the codebase and Gemfile.lock for other gems calling GitHub::Markup.markup/command with the colliding symbol."],"exampleFix":"# before\n# config/initializers/markup.rb - raises on Rails dev reload\nGitHub::Markup.command(:creole, 'creole', /creole\\z/, [])\n\n# after\nunless GitHub::Markup.markups.key?(:creole)\n  GitHub::Markup.command(:creole, 'creole', /creole\\z/, [])\nend","handlingStrategy":"validation","validationCode":"# Guard custom registrations against re-registration (Rails dev reload, double require):\nunless GitHub::Markup.markups.key?(:myengine)\n  GitHub::Markup.markup(:myengine, 'myengine-gem', /myext\\z/, [])\nend","typeGuard":null,"tryCatchPattern":"begin\n  GitHub::Markup.markup_impl(:custom, impl)\nrescue ArgumentError => e\n  raise unless e.message.include?('already defined')\n  # idempotent boot: symbol already registered by an earlier load, keep the existing one\n  log.info('markup :custom already registered; skipping')\nend","preventionTips":["Register custom renderers in a plain file loaded via require (not Rails autoload) so it evaluates exactly once per process.","Prefix custom symbols with an app or gem namespace (:acme_wiki) to avoid colliding with built-ins (:markdown, :rst, ...).","Assert the expected registry contents in a boot check: GitHub::Markup.markups.keys sort/compare against a fixture list."],"tags":["duplicate-registration","configuration","ruby","github-markup"],"backgroundTag":"duplicate-key-registration","analyzedSha":"76e2682193828b98471b3a071edf4db0590ccacb","analyzedAt":"2026-08-21T19:16:29.859Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}