{"record":{"id":"7d4fe058f9addb98","repo":"ruby-concurrency/concurrent-ruby","slug":"agent-is-not-failed","errorCode":null,"errorMessage":"agent is not failed","messagePattern":"agent is not failed","errorType":"exception","errorClass":"Concurrent::Agent::Error","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/agent.rb","lineNumber":427,"sourceCode":"    # then un-fails the Agent so that action dispatches are allowed again. If\n    # the `:clear_actions` option is give and true, any actions queued on the\n    # Agent that were being held while it was failed will be discarded,\n    # otherwise those held actions will proceed. The `new_value` must pass the\n    # validator if any, or `restart` will raise an exception and the Agent will\n    # remain failed with its old {#value} and {#error}. Observers, if any, will\n    # not be notified of the new state.\n    #\n    # @param [Object] new_value the new value for the Agent once restarted\n    # @param [Hash] opts the configuration options\n    # @option opts [Symbol] :clear_actions true if all enqueued but unprocessed\n    #   actions should be discarded on restart, else false (default: false)\n    # @return [Boolean] true\n    #\n    # @raise [Concurrent:AgentError] when not failed\n    def restart(new_value, opts = {})\n      clear_actions = opts.fetch(:clear_actions, false)\n      synchronize do\n        raise Error.new('agent is not failed') unless failed?\n        raise ValidationError unless ns_validate(new_value)\n        @current.value = new_value\n        @error.value   = nil\n        @queue.clear if clear_actions\n        ns_post_next_job unless @queue.empty?\n      end\n      true\n    end\n\n    class << self\n\n      # Blocks the current thread (indefinitely!) until all actions dispatched\n      # thus far to all the given Agents, from this thread or nested by the\n      # given Agents, have occurred. Will block when any of the agents are\n      # failed. Will never return if a failed Agent is restart with\n      # `:clear_actions` true.\n      #\n      # @param [Array<Concurrent::Agent>] agents the Agents on which to wait","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/agent.rb#L409-L445","documentation":"Agent#restart is the recovery path for an agent in :fail error mode whose action raised: it replaces the value, optionally clears queued actions, and resumes processing. Restoring a healthy agent is meaningless (its state is live and actions are flowing), so restart raises Agent::Error unless failed? is true.","triggerScenarios":"agent.restart(value) on an agent that never failed, or on one that already restarted - e.g. an unconditional restart in a supervision/recovery loop, or two threads that both observed the failure and both call restart (the second raises).","commonSituations":"Defensive supervision code calling restart 'just in case' each cycle; retry loops that restart on every iteration although only the first call is valid; races between multiple monitors of the same agent.","solutions":["Guard the call: agent.restart(new_value) if agent.failed?.","In supervision loops, re-check failed? each cycle and restart at most once per observed failure.","If you only want to change a healthy agent's value, use the normal update path (agent << new_value or agent.send { |old| ... }) - restart is not a setter."],"exampleFix":"# before\nagent.restart(fresh_value)   # raises unless the agent is failed\n\n# after\nif agent.failed?\n  agent.restart(fresh_value, clear_actions: true)\nelse\n  agent << fresh_value       # normal state change\nend","handlingStrategy":"validation","validationCode":"agent.restart(new_value, clear_actions: true) if agent.failed?","typeGuard":null,"tryCatchPattern":"begin\n  agent.restart(new_value)\nrescue Concurrent::Agent::Error\n  agent << new_value   # healthy agent: normal state change instead\nend","preventionTips":["Always gate restart on agent.failed?.","Restart at most once per observed failure; re-check failed? on every supervision cycle.","Use agent << value or agent.send { |old| ... } for ordinary state changes - restart is recovery-only."],"tags":["ruby","concurrent-ruby","agent","state-machine","error-recovery"],"backgroundTag":"invalid-state-transition","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}