Skip to content

Commit bed1f0f

Browse files
committed
docs: Document RubyLLM VertexAI fix and upstream PR
Documents the bug we found, our workaround, and the PR submitted to fix it upstream: crmne/ruby_llm#520
1 parent c0aec24 commit bed1f0f

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed

hub/docs/ruby_llm_vertexai_fix.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# RubyLLM VertexAI GCE Authentication Fix
2+
3+
## PR Submitted
4+
5+
**URL:** https://github.com/crmne/ruby_llm/pull/520
6+
7+
**Status:** Pending review
8+
9+
**Date:** 2025-12-01
10+
11+
## The Bug
12+
13+
When using RubyLLM 1.9.1 with the VertexAI provider on a Google Compute Engine VM, authentication fails with:
14+
15+
```
16+
TypeError: Expected Array or String, got Hash
17+
```
18+
19+
### Root Cause
20+
21+
In `lib/ruby_llm/providers/vertexai.rb`, the `initialize_authorizer` method passes `scope:` as a keyword argument:
22+
23+
```ruby
24+
# BROKEN - scope: is interpreted as a Hash
25+
@authorizer = ::Google::Auth.get_application_default(
26+
scope: [
27+
'https://www.googleapis.com/auth/cloud-platform',
28+
'https://www.googleapis.com/auth/generative-language.retriever'
29+
]
30+
)
31+
```
32+
33+
But `Google::Auth.get_application_default` expects scope as a **positional argument**:
34+
35+
```ruby
36+
# Method signature
37+
def get_application_default(scope = nil, options = {})
38+
```
39+
40+
Ruby interprets `scope: [...]` as passing a Hash `{scope: [...]}` to the first positional parameter, which the signet gem rejects.
41+
42+
### The Fix
43+
44+
Change from keyword to positional argument:
45+
46+
```ruby
47+
# FIXED - pass Array directly as positional argument
48+
@authorizer = ::Google::Auth.get_application_default(
49+
[
50+
'https://www.googleapis.com/auth/cloud-platform',
51+
'https://www.googleapis.com/auth/generative-language.retriever'
52+
]
53+
)
54+
```
55+
56+
## Our Workaround
57+
58+
Until the PR is merged and a new version released, we have a monkey-patch in place:
59+
60+
**File:** `config/initializers/ruby_llm_vertexai_patch.rb`
61+
62+
This patch overrides `RubyLLM::Providers::VertexAI#initialize_authorizer` with the correct positional argument syntax.
63+
64+
## How We Found This
65+
66+
1. Episode processing jobs were failing after deploying the URL-to-TTS feature
67+
2. Kamal logs showed `TypeError: Expected Array or String, got Hash`
68+
3. Stack trace pointed to `signet-0.21.0/lib/signet/oauth_2/client.rb:420`
69+
4. Traced back to `ruby_llm-1.9.1/lib/ruby_llm/providers/vertexai.rb:43`
70+
5. Discovered the keyword vs positional argument issue
71+
72+
### Full Stack Trace
73+
74+
```
75+
/gems/signet-0.21.0/lib/signet/oauth_2/client.rb:420:in 'Signet::OAuth2::Client#scope=': Expected Array or String, got Hash (TypeError)
76+
from /gems/signet-0.21.0/lib/signet/oauth_2/client.rb:193:in 'Signet::OAuth2::Client#update!'
77+
from /gems/googleauth-1.15.1/lib/googleauth/signet.rb:55:in 'Signet::OAuth2::Client#update!'
78+
from /gems/googleauth-1.15.1/lib/googleauth/compute_engine.rb:168:in 'Google::Auth::GCECredentials#update!'
79+
from /gems/signet-0.21.0/lib/signet/oauth_2/client.rb:115:in 'Signet::OAuth2::Client#initialize'
80+
from /gems/googleauth-1.15.1/lib/googleauth/compute_engine.rb:94:in 'Google::Auth::GCECredentials#initialize'
81+
from /gems/googleauth-1.15.1/lib/googleauth/application_default.rb:61:in 'Google::Auth.get_application_default'
82+
from /gems/ruby_llm-1.9.1/lib/ruby_llm/providers/vertexai.rb:43:in 'RubyLLM::Providers::VertexAI#initialize_authorizer'
83+
```
84+
85+
## Additional Issue Discovered
86+
87+
During debugging, we also discovered the GCE VM was missing the required OAuth scope. The VM needed `cloud-platform` scope to access Vertex AI APIs.
88+
89+
**Original VM scopes:**
90+
- `devstorage.read_only`
91+
- `logging.write`
92+
- `monitoring.write`
93+
- `service.management.readonly`
94+
- `servicecontrol`
95+
- `trace.append`
96+
97+
**Required scope:**
98+
- `https://www.googleapis.com/auth/cloud-platform`
99+
100+
The VM was recreated with the proper scope (new IP: 34.106.61.4).
101+
102+
## Environment
103+
104+
- ruby_llm 1.9.1
105+
- googleauth 1.15.1
106+
- signet 0.21.0
107+
- Ruby 3.4.5
108+
- Google Compute Engine VM
109+
- Rails 8.1.1
110+
111+
## Next Steps
112+
113+
1. **Wait for PR review** from RubyLLM maintainers
114+
2. **If merged:** Update Gemfile to new version and remove monkey-patch
115+
3. **If changes requested:** Address feedback and update PR
116+
117+
## Related Files
118+
119+
- `config/initializers/ruby_llm_vertexai_patch.rb` - Our temporary monkey-patch
120+
- `config/initializers/ruby_llm.rb` - RubyLLM configuration
121+
- `app/services/llm_client.rb` - Our LLM client wrapper
122+
123+
## Commits
124+
125+
- `4619e22` - fix: Patch RubyLLM 1.9.1 VertexAI auth bug on GCE
126+
- `c0aec24` - chore: Update VM IP address to 34.106.61.4

0 commit comments

Comments
 (0)