{"record":{"id":"c37c639b5a8f5b15","repo":"jordansissel/fpm","slug":"options-file-already-loaded-once-refusing-to-load","errorCode":null,"errorMessage":"Options file already loaded once. Refusing to load a second time. Maybe a file tries to load itself? Path: #{path}","messagePattern":"Options file already loaded once\\. Refusing to load a second time\\. Maybe a file tries to load itself\\? Path: #(.+?)","errorType":"validation","errorClass":"FPM::Package::InvalidArgument","httpStatus":null,"severity":"error","filePath":"lib/fpm/command.rb","lineNumber":610,"sourceCode":"\n    logger.warn(\"Additional options: #{flags.join \" \"}\") if flags.size > 0\n    logger.warn(\"Additional arguments: #{args.join \" \"}\") if args.size > 0\n\n    ARGV.unshift(*flags)\n    ARGV.push(*args)\n\n    super(run_args)\n  rescue FPM::Package::InvalidArgument => e\n    logger.error(\"Invalid package argument: #{e}\")\n    return 1\n  end # def run\n\n  def load_options(path)\n    @loaded_files ||= []\n\n    if @loaded_files.include?(path)\n      #logger.error(\"Options file was already loaded once. Refusing to load a second time.\", :path => path)\n      raise FPM::Package::InvalidArgument, \"Options file already loaded once. Refusing to load a second time. Maybe a file tries to load itself? Path: #{path}\"\n    end\n\n    if !File.exist?(path)\n      logger.fatal(\"Cannot load options from file because the file doesn't exist.\", :path => path)\n    end\n\n    if !File.readable?(path)\n      logger.fatal(\"Cannot load options from file because the file isn't readable.\", :path => path)\n    end\n\n    @loaded_files << path\n\n    logger.info(\"Loading flags from file\", :path => path)\n\n    # Safety check, abort if the file is huge. Arbitrarily chosen limit is 100kb\n    stat = File.stat(path)\n    max = 100 * 1024\n    if stat.size > max","sourceCodeStart":592,"sourceCodeEnd":628,"githubUrl":"https://github.com/jordansissel/fpm/blob/b6d77ba72a560b687723376a0e5115c3a92634ad/lib/fpm/command.rb#L592-L628","documentation":"load_options records every --fpm-options-file path in @loaded_files; encountering the same path a second time raises FPM::Package::InvalidArgument to break infinite recursion. In practice an options file includes itself, or two files include each other in a cycle.","triggerScenarios":"An options file containing its own path (--fpm-options-file ./fpm.conf listed inside fpm.conf); file A including B while B includes A; the same file referenced twice on one command line.","commonSituations":"Copy-pasting example configs that self-reference; refactoring shared flags into mutually-including files; generated configs that append their own loader line on each run.","solutions":["Remove the self-referencing --fpm-options-file line from the file","Restructure so one base file holds shared flags and only leaf configs include it (keep the include graph a tree)","Grep both sides of a cross-include pair and drop one direction"],"exampleFix":"# before: fpm.conf contains its own path\n--fpm-options-file ./fpm.conf\n--log debug\n\n# after: fpm.conf\n--log debug","handlingStrategy":"validation","validationCode":"path = File.expand_path('fpm.conf')\nFile.readlines(path).each do |line|\n  args = line.split\n  if (i = args.index('--fpm-options-file')) && args[i + 1] && File.expand_path(args[i + 1]) == path\n    abort 'options file includes itself; remove the self-referencing line'\n  end\nend","typeGuard":null,"tryCatchPattern":"begin\n  FPM::Command.run(%w[--fpm-options-file fpm.conf --version])\nrescue FPM::Package::InvalidArgument => e\n  abort \"options-file cycle detected: #{e.message}\"\nend","preventionTips":["Keep --fpm-options-file references acyclic: one shared base file included only by leaf configs","Never leave a file's own --fpm-options-file line inside the file itself","Smoke-test option files with 'fpm --fpm-options-file <file> --version' in CI"],"tags":["fpm","cli","config-file","include-cycle","recursion"],"backgroundTag":"circular-include","analyzedSha":"b6d77ba72a560b687723376a0e5115c3a92634ad","analyzedAt":"2026-08-21T16:39:02.570Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}