socketry/falcon · error · ArgumentError

Could not find config/serve.rb or config.ru in #{root}!

Error message

Could not find config/serve.rb or config.ru in #{root}!

What it means

Falcon's serve environment locates the application entry file by trying <root>/config/serve.rb and then <root>/config.ru whenever no explicit configuration_path is set (lib/falcon/environment/serve.rb:37-53). If both lookups miss, resolved_configuration_path raises ArgumentError naming the root it searched. Because middleware calls this resolver before anything loads, `falcon serve` aborts before any socket is bound, and the message tells you exactly which directory lacked the two files.

Source

Thrown at lib/falcon/environment/serve.rb:52

			
			# Resolve the application configuration path.
			# @returns [String] The absolute application configuration path.
			def resolved_configuration_path
				if configuration_path
					return File.expand_path(configuration_path, root)
				end
				
				serve_path = File.expand_path("config/serve.rb", root)
				if File.file?(serve_path)
					return serve_path
				end
				
				rackup_path = File.expand_path("config.ru", root)
				if File.file?(rackup_path)
					return rackup_path
				end
				
				raise ArgumentError, "Could not find config/serve.rb or config.ru in #{root}!"
			end
			
			# Load and wrap the configured application.
			# @returns [Protocol::HTTP::Middleware] The middleware stack.
			def middleware
				path = resolved_configuration_path
				
				case File.extname(path)
				when ".rb"
					application = ::Protocol::HTTP::Middleware.load(path)
					return ::Falcon::Server.protocol_middleware(application, verbose: verbose, cache: cache)
				when ".ru"
					application = ::Protocol::Rack::Adapter.parse_file(path)
					return ::Falcon::Server.rack_middleware(application, verbose: verbose, cache: cache)
				else
					raise ArgumentError, "Unsupported application configuration: #{path}!"
				end
			end

View on GitHub (pinned to 5107b0713f)

Solutions

  1. Create a minimal config.ru at the project root: run ->(env) { [200, {'content-type' => 'text/plain'}, ['ok']] }
  2. Or create config/serve.rb to use the Protocol::HTTP middleware-builder interface instead of Rack
  3. If the app file lives elsewhere, define configuration_path in your Falcon environment; it is expanded relative to root and bypasses discovery
  4. Fix the working directory of the launching process (systemd WorkingDirectory, Docker WORKDIR) so root is the app root

Example fix

# before: falcon serve in a directory with neither config.ru nor config/serve.rb
#   ArgumentError: Could not find config/serve.rb or config.ru in /srv/app!

# after (option 1): create config.ru in the app root
# config.ru
require_relative 'config/application'
run MyApp

# after (option 2): explicit path in the falcon environment
class MyAppEnvironment
  include Falcon::Environment::Serve

  def configuration_path
    'apps/web/config.ru' # expanded relative to root; skips discovery
  end
end
Defensive patterns

Strategy: validation

Validate before calling

# Run before starting falcon / calling environment.middleware
def falcon_config_available?(environment)
  if (path = environment.configuration_path)
    return File.file?(File.expand_path(path, environment.root))
  end

  %w[config/serve.rb config.ru].any? do |relative|
    File.file?(File.expand_path(relative, environment.root))
  end
end

unless falcon_config_available?(environment)
  abort "No config/serve.rb or config.ru under #{environment.root}; create one or set configuration_path"
end

Try / catch

begin
  middleware = environment.middleware
rescue ArgumentError => error
  abort "falcon serve: #{error.message} (create config.ru or set configuration_path)"
end

Prevention

When it happens

Trigger: Calling `falcon serve`, or Falcon::Environment::Serve#middleware / #resolved_configuration_path, when configuration_path returns nil and neither <root>/config/serve.rb nor <root>/config.ru exists — e.g. an empty project directory, a custom environment whose root resolves elsewhere, or a launcher (systemd, Docker, daemon) whose working directory is not the app root.

Common situations: Fresh project with no rackup file yet; running falcon from a subdirectory or under systemd/Docker where cwd differs from the app root; a config.ru living in a subfolder (apps/web/config.ru) while root points at the repo root; a custom environment that overrides root but leaves configuration_path nil.

Related errors


AI-assisted analysis of socketry/falcon@5107b0713f (2026-08-23). Data as JSON: /api/errors/0aba9e7ef13b53da. Report an issue: GitHub.