# HELP! Rake aborted! Can't modify frozen hash

**URL:** <https://www.ruby-forum.com/t/help-rake-aborted-cant-modify-frozen-hash/186276>\
**Category:** Rails\
**Created:** [April 3, 2010, 1:27pm UTC](https://www.ruby-forum.com/t/help-rake-aborted-cant-modify-frozen-hash/186276 "2010-04-03T13:27:54Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![patrick\_nicholas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a698b9/32.png) [@patrick\_nicholas](https://www.ruby-forum.com/u/patrick_nicholas)\
**Post date:** [April 3, 2010, 1:27pm UTC](https://www.ruby-forum.com/t/help-rake-aborted-cant-modify-frozen-hash/186276/1 "2010-04-03T13:27:54Z")

</div>

Too bad even the trace doesn’t say which hash is involved.

Sorry this post is long: am trying to provide enough context to be  
meaningful.

Occurs _intermittently_ when rake jobs:work is pulling a command out  
of delayed\_jobs while my status observer is in the process of parsing  
a log file for detailed results of the previous delayed\_job denizen.  
I have an observer class (in RAILS\_ROOT/lib ) which listens for the  
events, makes a copy of them and calls the owner class ( in apps/  
models ) which then calls on the log parser (also in /lib) to do the  
actual work. (Should both of those classes, the observer and the  
parser be in app/models?)

Am due to deliver this application in a few days and this is killing  
it (and me).

Am using DirectoryWatcher to look for flag files that indicate the  
start and finish of the delayed\_jobs.  
That is started at the end of environment.rb like this:

require ‘directory\_watcher’  
$scriptStatusObserver = ScriptStatusObserver.new  
dirToWatch ="#{RAILS\_ROOT}/tmp/flags"  
$directoryWatcher = DirectoryWatcher.new( dirToWatch )  
$directoryWatcher.glob= “\*.flg”  
$directoryWatcher.interval=(15)  
$directoryWatcher.add\_observer( $scriptStatusObserver )  
$directoryWatcher.persist=("#{RAILS\_ROOT}/tmp/flags/dw\_state.yml")  
$directoryWatcher.start

at\_exit { $directoryWatcher.stop }

This code is outside of the run method (btw is that the best place or  
is inside the run better?)

Here is the observer:  
require ‘script\_run’

class ScriptStatusObserver

def initialize  
@rcvdEvents = []  
end

def update( \*events )  
begin  
puts “#{ **LINE**.to\_s}: ScriptStatusObserver events:  
\n”+events.to\_yaml  
cnt = 0

```
  events.each do |e|
    if e.to_s.match(/^\s*added/)
      cnt = cnt + 1
    @rcvdEvents << e
    end
  end

  ScriptRun.new.catch_up( @rcvdEvents ) if cnt > 0

  @rcvdEvents.clear

rescue
  puts $!
end

```

end  
end

Here is ScriptRun (it attaches to an associative table built with  
has\_many:through)

#require ‘observer’

class ScriptRun \< ActiveRecord::Base

set\_table\_name “scripts\_runs”  
belongs\_to :script  
belongs\_to :run

def parse( result )  
parser = LogParser.new  
parser.parse(result)  
end

def catch\_up( events )  
events.each do |e|  
typ = e.type  
path = e.path

```
  thisMatch = path.match(/flags\/(\d+)_(\d+)_([\d\.]+)_(\w+)

```

.flg/)  
run\_id = thisMatch[1]  
script\_id = thisMatch[2]  
ts = thisMatch[3]  
status = thisMatch[4]

```
  if e.to_s.match(/^\s*added/)
    status_update( script_id, run_id, status, ts, path )
  end
end

```

end

def status\_update( script\_id, run\_id, status, ts, path )

```
scriptrun = ScriptRun.find(:first, :conditions => [ "run_id = ?

```

and script\_id = ?", run\_id.to\_i, script\_id.to\_i ])

```
if scriptrun.kind_of?(ScriptRun)
  currStatus = scriptrun.status
  if not currStatus == 'completed'

    scriptrun.update_attribute(:status, status)

    if status == 'parse'
      flag = File.new(path)
      logSpec = flag.gets
      flag.close

      logName = File.basename(logSpec)
      logPath = logSpec.sub(logName, '')

      logName =~ /^(([\w_]+)_([\w]+)_(\d+))\.log$/
      name = $1
      basename = $2
      runenv = $3
      tsOrPid = $4

      result = Result.new
      result.log_path = logPath
      result.basename = basename
      result.name = name
      result.script_id = script_id.to_i
      result.run_id = run_id.to_i
      if runenv == 'sit'
          runenv = 'SIT3348'
      end
      result.application_environment_id =
            ApplicationEnvironment.find(:first, :conditions =>

```

[“nodename = ?”, runenv]).id

```
      parse(result)

      if run_completed?( run_id )
        myRun = Run.find(run_id.to_i)
        if myRun.kind_of?( Run )
          myRun.update_attribute( :completed, Time.now.to_f )
        end
      end

    end
  end

else
  puts "#{ __LINE__.to_s}: ScriptRun.status_update: ScriptRun not

```

found for run #{run\_id} script #{script\_id} ts #{ts.to\_s}"  
end

File.delete(path)

end

def run\_completed?( id )  
scriptruns = ScriptRun.find(:all, :conditions =\> [ “run\_id = ?”,  
id.to\_i] )  
scriptruns.each do |sr|  
if not sr.status == ‘completed’  
return false  
end  
end  
return true  
end  
end

LogParser is too long even for this post but it reads the script log  
and pulls detailed information (counts and timings) out of the log and  
writes to a details table. It also tallies and calculates averages and  
rolls those up into summary tables for quicker access from the web  
pages.

Here is the error trace:  
(don’t ask why everything is under my Windows profile. It’s a long  
story)

Scanner running 1270239731.43  
directory\_watcher.notify\_observers: #\<ScriptStatusObserver:0x48ae838  
@rcvdEvents  
=[#, #]\>  
update:[#,  
#]  
rake aborted!  
can’t modify frozen hash  
C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/rails/  
activerecord/l  
ib/active\_record/attribute\_methods.rb:313:in `[]=' C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/rails/ activerecord/l ib/active_record/attribute_methods.rb:313:in`write\_attribute\_without\_dirty’  
C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/rails/  
activerecord/l  
ib/active\_record/dirty.rb:139:in `write_attribute' C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/rails/ activerecord/l ib/active_record/attribute_methods.rb:211:in`last\_error=’  
C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/  
delayed\_job/  
lib/delayed/worker.rb:141:in `handle_failed_job' C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/ delayed_job/ lib/delayed/worker.rb:115:in`run’  
C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/  
delayed\_job/  
lib/delayed/worker.rb:162:in `reserve_and_run_one_job' C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/ delayed_job/ lib/delayed/worker.rb:92:in`work\_off’  
C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/  
delayed\_job/  
lib/delayed/worker.rb:91:in `times' C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/ delayed_job/ lib/delayed/worker.rb:91:in`work\_off’  
C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/  
delayed\_job/  
lib/delayed/worker.rb:66:in `start' C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/rails/ activesupport/ lib/active_support/core_ext/benchmark.rb:10:in`realtime’  
C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/  
delayed\_job/  
lib/delayed/worker.rb:65:in `start' C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/ delayed_job/ lib/delayed/worker.rb:62:in`loop’  
C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/  
delayed\_job/  
lib/delayed/worker.rb:62:in `start' C:/Documents and Settings/pneve/workspace/waftt-0.29/vendor/plugins/ delayed_job/ lib/delayed/tasks.rb:13 c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake. rb:636:in`call’  
c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/  
lib/rake.  
rb:636:in `execute' c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake. rb:631:in`each’  
c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/  
lib/rake.  
rb:631:in `execute' c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake. rb:597:in`invoke\_with\_call\_chain’  
c:/Documents and Settings/pneve/ruby/lib/ruby/1.8/monitor.rb:242:in  
`synchronize ' c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake. rb:590:in`invoke\_with\_call\_chain’  
c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/  
lib/rake.  
rb:583:in `invoke' c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake. rb:2051:in`invoke\_task’  
c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/  
lib/rake.  
rb:2029:in `top_level' c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake. rb:2029:in`each’  
c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/  
lib/rake.  
rb:2029:in `top_level' c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake. rb:2068:in`standard\_exception\_handling’  
c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/  
lib/rake.  
rb:2023:in `top_level' c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake. rb:2001:in`run’  
c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/  
lib/rake.  
rb:2068:in `standard_exception_handling' c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake. rb:1998:in`run’  
c:/Documents and Settings/pneve/ruby/lib/ruby/gems/1.8/gems/rake-0.8.7/  
bin/rake:  
31  
c:/Documents and Settings/pneve/ruby/bin/rake:16:in `load’  
c:/Documents and Settings/pneve/ruby/bin/rake:16
