{"record":{"id":"2d8d1cc1eeeb770e","repo":"jordansissel/fpm","slug":"file-already-exists-refusing-to-continue-outpu","errorCode":null,"errorMessage":"File already exists, refusing to continue: #{output_path}","messagePattern":"File already exists, refusing to continue: #(.+?)","errorType":"validation","errorClass":"FPM::Package::FileAlreadyExists","httpStatus":null,"severity":"error","filePath":"lib/fpm/package.rb","lineNumber":539,"sourceCode":"      erb = erbnew(scripts[script_name])\n      # TODO(sissel): find the original file name for the file.\n      erb.filename = \"script(#{script_name})\"\n      return erb.result(binding)\n    else\n      return scripts[script_name]\n    end\n  end # def script\n\n  def output_check(output_path)\n    if !File.directory?(File.dirname(output_path))\n      raise ParentDirectoryMissing.new(output_path)\n    end\n    if File.file?(output_path)\n      if attributes[:force?]\n        logger.warn(\"Force flag given. Overwriting package at #{output_path}\")\n        File.delete(output_path)\n      else\n        raise FileAlreadyExists.new(output_path)\n      end\n    end\n  end # def output_path\n\n  def provides=(value)\n    if !value.is_a?(Array)\n      @provides = [value]\n    else\n      @provides = value\n    end\n  end # def provides=\n\n  # General public API\n  public(:type, :initialize, :convert, :input, :output, :to_s, :cleanup, :files,\n         :version, :script, :provides=)\n\n  # Package internal public api\n  public(:cleanup_staging, :cleanup_build, :staging_path, :converted_from,","sourceCodeStart":521,"sourceCodeEnd":557,"githubUrl":"https://github.com/jordansissel/fpm/blob/b6d77ba72a560b687723376a0e5115c3a92634ad/lib/fpm/package.rb#L521-L557","documentation":"The second half of output_check: if the target package file already exists and --force was not given, FileAlreadyExists is raised instead of silently overwriting. This protects previously built artifacts; with attributes[:force?] (the -f flag) fpm logs a warning and deletes the file before rebuilding.","triggerScenarios":"Rebuilding the same name/version/iteration to the same -p path (default output filenames include the version, so unchanged versions collide); CI re-runs without workspace cleanup; API pkg.output(path) without setting attributes[:force?].","commonSituations":"Iterating locally on the same unreleased version; CI retrying a job into a dirty workspace; artifacts directory shared between matrix jobs writing identical filenames.","solutions":["Pass -f/--force when overwriting is intended: fpm -f -p dist/app.deb ...","Clean the output dir in the build script (rm -f dist/*.deb) for reproducible rebuilds","Bump --iteration or embed a git SHA/timestamp in the -p filename so builds never collide"],"exampleFix":"# before\nfpm -s dir -t deb -p dist/app_1.0_amd64.deb ./app   # file left by previous build\n\n# after\nfpm -s dir -t deb -f -p dist/app_1.0_amd64.deb ./app","handlingStrategy":"validation","validationCode":"out = File.expand_path('dist/app_1.0_amd64.deb')\nFile.delete(out) if File.exist?(out)   # or pass -f / attributes[:force?] = true\nsystem('fpm', '-s', 'dir', '-t', 'deb', '-p', out, './app')","typeGuard":null,"tryCatchPattern":"begin\n  pkg.output(out)\nrescue FPM::Package::FileAlreadyExists\n  warn \"#{out} exists; bump --iteration or pass --force\"\n  raise\nend","preventionTips":["Make rebuilds idempotent: rm -f dist/* before fpm, or always pass -f in CI","Include build numbers or git SHAs in output filenames to avoid collisions","Treat an unexpected FileAlreadyExists as a signal that version/iteration was not bumped"],"tags":["fpm","filesystem","output-path","overwrite","ci"],"backgroundTag":"file-already-exists","analyzedSha":"b6d77ba72a560b687723376a0e5115c3a92634ad","analyzedAt":"2026-08-21T16:39:02.570Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}