Skip to content

[Bug]: Plot command requires image gen provider credentials even not used #201

@xraywu

Description

@xraywu

What happened?

Plot only uses vlm provider. However, when triggering the command, it still validates if a GEMINI API Key exists for image gen.

Steps to reproduce

  1. Do not set GOOGLE_API_KEY env.
  2. Run the below command:uv run paperbanana plot --data .\data.csv --intent "Model accuracy comparison" --aspect-ratio 16:9 --vlm-provider openai

Input used

uv run paperbanana plot --data .\data.csv --intent "Model accuracy comparison"  --aspect-ratio 16:9  --vlm-provider openai

Expected behavior

Should not validate if this api key exists and process the plot task

Actual output or error

uv run paperbanana plot --data .\data.csv --intent "Model accuracy comparison"  --aspect-ratio 16:9  --vlm-provider openai                    
╭───────────────────────────────────────────╮
│ PaperBanana - Generating Statistical Plot │
│                                           │
│ Data: data.csv                            │
│ Intent: Model accuracy comparison         │
│ VLM: openai / gpt-5.5                     │
│ Iterations: 3                             │
╰───────────────────────────────────────────╯
╭────────────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────────╮
│ D:\test\cli.py:2039 in plot                                          │
│                                                                                                                       │
│   2036 │   │   pipeline = PaperBananaPipeline(settings=settings)                                                      │
│   2037 │   │   return await pipeline.generate(gen_input)                                                              │
│   2038 │                                                                                                              │
│ ❱ 2039 │   result = asyncio.run(_run())                                                                               │
│   2040 │   console.print(f"\n[green]Done![/green] Plot saved to: [bold]{result.image_path}[/bold]")                   │
│   2041 │   vector_paths = result.metadata.get("vector_output_paths", {})                                              │
│   2042 │   for fmt, path in vector_paths.items():                                                                     │
│                                                                                                                       │
│ C:\Users\test\AppData\Roaming\uv\python\cpython-3.12.12-windows-x86_64-none\Lib\asyncio\runners.py:195 in run    │
│                                                                                                                       │
│   192 │   │   │   "asyncio.run() cannot be called from a running event loop")                                         │
│   193 │                                                                                                               │
│   194 │   with Runner(debug=debug, loop_factory=loop_factory) as runner:                                              │
│ ❱ 195 │   │   return runner.run(main)                                                                                 │
│   196                                                                                                                 │
│   197                                                                                                                 │
│   198 def _cancel_all_tasks(loop):                                                                                    │
│                                                                                                                       │
│ C:\Users\test\AppData\Roaming\uv\python\cpython-3.12.12-windows-x86_64-none\Lib\asyncio\runners.py:118 in run    │
│                                                                                                                       │
│   115 │   │                                                                                                           │
│   116 │   │   self._interrupt_count = 0                                                                               │
│   117 │   │   try:                                                                                                    │
│ ❱ 118 │   │   │   return self._loop.run_until_complete(task)                                                          │
│   119 │   │   except exceptions.CancelledError:                                                                       │
│   120 │   │   │   if self._interrupt_count > 0:                                                                       │
│   121 │   │   │   │   uncancel = getattr(task, "uncancel", None)                                                      │
│                                                                                                                       │
│ C:\Users\test\AppData\Roaming\uv\python\cpython-3.12.12-windows-x86_64-none\Lib\asyncio\base_events.py:691 in    │
│ run_until_complete                                                                                                    │
│                                                                                                                       │
│    688 │   │   if not future.done():                                                                                  │
│    689 │   │   │   raise RuntimeError('Event loop stopped before Future completed.')                                  │
│    690 │   │                                                                                                          │
│ ❱  691 │   │   return future.result()                                                                                 │
│    692 │                                                                                                              │
│    693 │   def stop(self):                                                                                            │
│    694 │   │   """Stop running the event loop.                                                                        │
│                                                                                                                       │
│ D:\test\cli.py:2036 in _run                                          │
│                                                                                                                       │
│   2033 │   from paperbanana.core.pipeline import PaperBananaPipeline                                                  │
│   2034 │                                                                                                              │
│   2035 │   async def _run():                                                                                          │
│ ❱ 2036 │   │   pipeline = PaperBananaPipeline(settings=settings)                                                      │
│   2037 │   │   return await pipeline.generate(gen_input)                                                              │
│   2038 │                                                                                                              │
│   2039 │   result = asyncio.run(_run())                                                                               │
│                                                                                                                       │
│ D:\test\core\pipeline.py:190 in __init__                             │
│                                                                                                                       │
│    187 │   │   │   self._demo_mode = True                                                                             │
│    188 │   │   else:                                                                                                  │
│    189 │   │   │   self._vlm = ProviderRegistry.create_vlm(self.settings)                                             │
│ ❱  190 │   │   │   self._image_gen = ProviderRegistry.create_image_gen(self.settings)                                 │
│    191 │   │   │   self._demo_mode = False                                                                            │
│    192 │   │                                                                                                          │
│    193 │   │   # Cost tracking (optional — active when budget is set or always for reporting)                         │
│                                                                                                                       │
│ D:\test\providers\registry.py:173 in create_image_gen                │
│                                                                                                                       │
│   170 │   │   logger.info("Creating image gen provider", provider=provider, model=settings.image_model)               │
│   171 │   │                                                                                                           │
│   172 │   │   if provider == "google_imagen":                                                                         │
│ ❱ 173 │   │   │   _validate_api_key(settings.google_api_key, "GOOGLE_API_KEY")                                        │
│   174 │   │   │   from paperbanana.providers.image_gen.google_imagen import GoogleImagenGen                           │
│   175 │   │   │                                                                                                       │
│   176 │   │   │   return GoogleImagenGen(                                                                             │
│                                                                                                                       │
│ D:\test\providers\registry.py:60 in _validate_api_key                │
│                                                                                                                       │
│    57 │   """Raise a helpful error if the required API key is missing."""                                             │
│    58 │   if key_value is None or not key_value.strip():                                                              │
│    59 │   │   hint = _API_KEY_HINTS.get(env_var_name, f"{env_var_name} is not set.")                                  │
│ ❱  60 │   │   raise ValueError(hint)                                                                                  │
│    61                                                                                                                 │
│    62                                                                                                                 │
│    63 def _validate_bedrock_auth(region: str, profile: str | None) -> None:                                           │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
ValueError: GOOGLE_API_KEY not found.

To fix this:
  1. Get a free API key at: https://makersuite.google.com/app/apikey
  2. Run: paperbanana setup

Or set it manually:
  export GOOGLE_API_KEY=your-key-here

Operating system

Windows 11

Python version

3.12

PaperBanana version or commit hash

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions