# Sometimes "Ruby exception occurred: no implicit conversion of nil into String"

**URL:** <https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401>\
**Category:** Logstash\
**Created:** [June 11, 2018, 3:53pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401 "2018-06-11T15:53:24Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![vb4t](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vb4t](https://discuss.elastic.co/u/vb4t)\
**Post date:** [June 11, 2018, 3:53pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/1 "2018-06-11T15:53:24Z")

</div>

Hello,

I use following ruby code in ruby filter to remove empty fields and fields containing "-" from fields nested in "parentfield" . The code works 99% time well, but sometimes I get ruby exception "Ruby exception occurred: no implicit conversion of nil into String". What is wrong with this code?

```
  ruby {
    code => "
      def walk_hash(parent, path, hash)
        path << parent if parent
        hash.each do |key, value|
          walk_hash(key, path, value) if value.is_a?(Hash)
          @paths << (path + [key]).map {|p| '[' + p + ']' }.join('')
        end
        path.pop
      end

      @paths = []
      eventhash = event.to_hash
      if eventhash.has_key?('parentfield') && eventhash['parentfield'].is_a?(Hash)
        walk_hash('parentfield', [], eventhash['parentfield'])
      end

      @paths.each do |path|
        value = event.get(path)
        event.remove(path) if value.nil? || (value.respond_to?(:empty?) && value.empty?) || (value.is_a?(String) && value == '-')
      end
    "
  }
```

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [June 11, 2018, 4:10pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/2 "2018-06-11T16:10:05Z")

</div>

Can you show us a document that triggered that ruby exception?

---

<div class="post-metadata">

**Author:** ![vb4t](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vb4t](https://discuss.elastic.co/u/vb4t)\
**Post date:** [June 11, 2018, 4:24pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/3 "2018-06-11T16:24:33Z")

</div>

...

It seems if I change this line:  
`event.remove(path) if value.nil? || (value.respond_to?(:empty?) && value.empty?) || (value.is_a?(String) && value == '-')`  
to this:  
`event.remove(path) if value.nil? || (value.respond_to?(:empty?) && value.empty?)`  
the issue disappears. But this will not do what I want. It will just remove empty fields (yes, almost all '-' fields shown in kibana means the value is null, but sometimes there is a - char).

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [June 11, 2018, 4:30pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/4 "2018-06-11T16:30:04Z")

</div>

> [@vb4t](#):
>
> (value.is\_a?(String) && value == '-')

So have a second event.remove(path) that is conditional on the value not being nil and also meeting that condition.

---

<div class="post-metadata">

**Author:** ![vb4t](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vb4t](https://discuss.elastic.co/u/vb4t)\
**Post date:** [June 11, 2018, 4:32pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/5 "2018-06-11T16:32:55Z")

</div>

Yes, I will try. But should not be `event.remove(path) if value.nil? || (value.respond_to?(:empty?) && value.empty?) || (value.is_a?(String) && value == '-')` working?

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [June 11, 2018, 4:53pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/6 "2018-06-11T16:53:21Z")

</div>

You mean that if value is nil you would expect if value.nil? to evaluate to true, resulting in all the ||'d conditions being short-circuited so that && value == '-' never gets evaluated? You might expect that, but you are telling me it does not work that way 😃

---

<div class="post-metadata">

**Author:** ![vb4t](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vb4t](https://discuss.elastic.co/u/vb4t)\
**Post date:** [June 11, 2018, 4:56pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/7 "2018-06-11T16:56:47Z")

</div>

Even if || will be processed all (which should not), `(value.is_a?(String) && value == '-')` contains condition to ensure value is String.  
But I tried to do it in separate condition, so:

```
  unless value.nil?
    event.remove(path) if (value.is_a?(String) && value == '-')
  end

```

It causes the same issue.

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [June 11, 2018, 5:14pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/8 "2018-06-11T17:14:37Z")

</div>

If I wrap that object in { "parentfield" : ... } then with 6.2.4 your ruby script strips out all the nulls without throwing an exception.

---

<div class="post-metadata">

**Author:** ![vb4t](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vb4t](https://discuss.elastic.co/u/vb4t)\
**Post date:** [June 11, 2018, 5:26pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/9 "2018-06-11T17:26:07Z")

</div>

The content of parentfield is not the raw json, but json decoded data, so there is parentfield.applicaitonname, parentfield.operation\_o.id, ...

---

<div class="post-metadata">

**Author:** ![vb4t](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vb4t](https://discuss.elastic.co/u/vb4t)\
**Post date:** [June 11, 2018, 5:27pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/10 "2018-06-11T17:27:03Z")

</div>

It can take about an hour and lot of events before I can see ruby exception. So it does not occur all the time.

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [June 11, 2018, 5:54pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/11 "2018-06-11T17:54:19Z")

</div>

If @paths is shared between threads it could get stepped on. Have you tried --pipeline.workers 1 ?

---

<div class="post-metadata">

**Author:** ![vb4t](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vb4t](https://discuss.elastic.co/u/vb4t)\
**Post date:** [June 11, 2018, 6:07pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/12 "2018-06-11T18:07:03Z")

</div>

It can not be shared between threads. @var is instance variable. I hope instance var is per thread (or is it per plugin instance globally?). There are too many events to be handled by just 1 worker. Also it could lead to a much longer time for the issue to occur so I can not test this.  
I will try to change @paths to local variable (paths).

---

<div class="post-metadata">

**Author:** ![vb4t](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vb4t](https://discuss.elastic.co/u/vb4t)\
**Post date:** [June 11, 2018, 6:26pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/13 "2018-06-11T18:26:51Z")

</div>

Hmm, it looks like there is one instance of one plugin configuration for each pipeline across all pipeline threads so probably @instance vars are shared ...

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [June 11, 2018, 6:48pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/14 "2018-06-11T18:48:23Z")

</div>

> [@vb4t](#):
>
> so probably @instance vars are shared

Yes, they are. You can demonstrate that using this (after setting pipeline.batch.size: 1)

```auto
input { generator { count => 3 message => '' } }

filter {
    ruby {
        code => "
            if @a.nil?
                @a = rand
            end
            event.set('a', @a)
            event.set('id', Thread.current.object_id)
        "
    }
}
output { stdout { codec => rubydebug } }

```

The first two events may have different random numbers because they both test @a is nil at the same time, but after that every event has the same random number. For example...

```auto
{
             "a" => 0.788757598293314,
      "sequence" => 0,
    "@timestamp" => 2018-06-11T18:44:59.526Z,
            "id" => 2012
}
{
             "a" => 0.7908474711636193,
      "sequence" => 1,
    "@timestamp" => 2018-06-11T18:44:59.529Z,
            "id" => 2010
}
{
             "a" => 0.788757598293314,
      "sequence" => 3,
    "@timestamp" => 2018-06-11T18:44:59.529Z,
            "id" => 2010
}
{
             "a" => 0.788757598293314,
      "sequence" => 2,
    "@timestamp" => 2018-06-11T18:44:59.529Z,
            "id" => 2012
}

```

---

<div class="post-metadata">

**Author:** ![vb4t](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vb4t](https://discuss.elastic.co/u/vb4t)\
**Post date:** [June 11, 2018, 7:40pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/15 "2018-06-11T19:40:10Z")

</div>

I can confirm after change to local vars it is working correctly. Thanks very much. This is the working solution:

```
  ruby {
    code => "
      def walk_hash(parent, path, hash, paths)
        path << parent if parent
        hash.each do |key, value|
          walk_hash(key, path, value, paths) if value.is_a?(Hash)
          paths << (path + [key]).map {|p| '[' + p + ']' }.join('')
        end
        path.pop
      end

      eventhash = event.to_hash
      if eventhash.has_key?('SOMEFIELD') && eventhash['SOMEFIELD'].is_a?(Hash)
        paths = []
        walk_hash('SOMEFIELD', [], eventhash['SOMEFIELD'], paths)
        paths.each do |path|
          value = event.get(path)
          event.remove(path) if value.nil? || (value.respond_to?(:empty?) && value.empty?) [+ '-' condition if wanted]
        end
      end
    "
  }
```

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [July 9, 2018, 7:40pm UTC](https://discuss.elastic.co/t/sometimes-ruby-exception-occurred-no-implicit-conversion-of-nil-into-string/135401/16 "2018-07-09T19:40:11Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
