{"record":{"id":"e6178fbd457092b9","repo":"ruby/ruby","slug":"empty-parent-path","errorCode":null,"errorMessage":"empty parent path","messagePattern":"empty parent path","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/tmpdir.rb","lineNumber":162,"sourceCode":"    # Dedicated random number generator\n    RANDOM = Object.new\n    class << RANDOM # :nodoc:\n      # Maximum random number\n      MAX = 36**6 # < 0x100000000\n\n      # Returns new random string upto 6 bytes\n      def next\n        (::Random.urandom(4).unpack1(\"L\")%MAX).to_s(36)\n      end\n    end\n    RANDOM.freeze\n    private_constant :RANDOM\n\n    # Generates and yields random names to create a temporary name\n    def create(basename, tmpdir=nil, max_try: nil, **opts)\n      if tmpdir\n        origdir = tmpdir = File.path(tmpdir)\n        raise ArgumentError, \"empty parent path\" if tmpdir.empty?\n      else\n        tmpdir = tmpdir()\n      end\n      n = nil\n      prefix, suffix = basename\n      prefix = (String.try_convert(prefix) or\n                raise ArgumentError, \"unexpected prefix: #{prefix.inspect}\")\n      prefix = prefix.delete(UNUSABLE_CHARS)\n      suffix &&= (String.try_convert(suffix) or\n                  raise ArgumentError, \"unexpected suffix: #{suffix.inspect}\")\n      suffix &&= suffix.delete(UNUSABLE_CHARS)\n      begin\n        t = Time.now.strftime(\"%Y%m%d\")\n        path = \"#{prefix}#{t}-#{$$}-#{RANDOM.next}\"\\\n               \"#{n ? %[-#{n}] : ''}#{suffix||''}\"\n        path = File.join(tmpdir, path)\n        yield(path, n, opts, origdir)\n      rescue Errno::EEXIST","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/lib/tmpdir.rb#L144-L180","documentation":"Tmpname.create (backing Dir.mktmpdir, Dir.mktmpname and friends) raises ArgumentError 'empty parent path' when an explicit tmpdir argument was supplied but File.path(tmpdir) resolves to \"\". It guards against joining the temp name onto an empty string, which would silently create hidden files in the current directory.","triggerScenarios":"Dir.mktmpdir(\"x\", \"\"); passing ENV['TMPDIR'] when it is set-but-empty (common in CI-scrubbed environments); blank config values interpolated into a dir argument.","commonSituations":"Kubernetes/CI env sanitizers that set TMPDIR=\"\" instead of unsetting it; config where tmp_dir: is an empty string default; Pathname or String inputs that reduce to empty after trimming.","solutions":["Normalize empty to nil so the default Dir.tmpdir is used: dir = (s = ENV['TMPDIR']).to_s.empty? ? nil : s","Validate config at load time: reject or default blank tmp_dir entries","Unset rather than empty the variable in CI sanitizers: ENV.delete('TMPDIR') when blank","Pass no dir argument when you have nothing meaningful to pass"],"exampleFix":"# before\nDir.mktmpdir(\"job-\", ENV[\"TMPDIR\"])    # TMPDIR is \"\" -> raises: empty parent path\n\n# after\ntmp = ENV[\"TMPDIR\"]\ntmp = nil if tmp.to_s.empty?\nDir.mktmpdir(\"job-\", tmp)","handlingStrategy":"validation","validationCode":"tmp = ENV['TMPDIR']\ntmp = nil if tmp.to_s.empty?\nDir.mktmpdir('job-', tmp)","typeGuard":null,"tryCatchPattern":"begin\n  Dir.mktmpdir('job-', dir)\nrescue ArgumentError => e\n  raise unless e.message.include?('empty parent path')\n  Dir.mktmpdir('job-')  # fall back to default tmpdir\nend","preventionTips":["Treat set-but-empty TMPDIR as unset in environment loading code","Validate tmp_dir config entries are non-blank strings","In CI sanitizers, ENV.delete('TMPDIR') instead of assigning \"\""],"tags":["ruby","tmpdir","environment","path-validation"],"backgroundTag":"empty-tmpdir-env-var","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}