DEV Community

Quinn Zhu
Quinn Zhu

Posted on

I Gave My Git History to a Free AI Bot. It Broke 7 Times in 3 Days.

Last Tuesday, I built a bot. It reads my project's git log every night. It writes a plain-English summary of the day's changes. I hosted it on MonkeyCode's free server with the free token tier.

Three days later, I had an error-log folder and zero trust in "free" infrastructure.

This is the debugging log. Seven failures. Seven fixes. Each one taught me something about free AI infrastructure.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

Free tier numbers change. Verify current terms in the dashboard before you depend on them.

The Setup

The bot is simple. A cron job runs at 23:00. It collects the last 20 commits. It sends them to the model. It posts the summary to a Slack webhook.

# summarize.py
import subprocess
import os
from openai import OpenAI

client = OpenAI(
    base_url=os.getenv("LLM_BASE_URL"),
    api_key=os.getenv("LLM_API_KEY"),
)

log = subprocess.run(
    ["git", "log", "--oneline", "-20"],
    capture_output=True, text=True
).stdout

response = client.chat.completions.create(
    model=os.getenv("LLM_MODEL"),
    messages=[
        {"role": "system", "content": "Summarize these commits for a non-technical stakeholder."},
        {"role": "user", "content": log},
    ],
)

print(response.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

Simple. Naive. Wrong in seven ways.

Failure 1: The Read Timeout

Symptom: The first run died after 60 seconds.

requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='api...', port=443): Read timed out.
Enter fullscreen mode Exit fullscreen mode

Diagnosis: The model took longer than the default 60-second timeout. Free-tier servers are not fast. The git log was long. The model had a lot to read.

Fix: Raise the timeout. Add retries with exponential backoff.

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=30))
def call_model(messages):
    return client.chat.completions.create(
        model=os.getenv("LLM_MODEL"),
        messages=messages,
        timeout=120,
    )
Enter fullscreen mode Exit fullscreen mode

Verify: Run the script. Watch it survive past 60 seconds.

Failure 2: Markdown-Wrapped JSON

Symptom: The bot printed a JSON object wrapped in a code fence.

```json
{"summary": "..."}
```
Enter fullscreen mode Exit fullscreen mode

Diagnosis: The model decided to be helpful and add syntax highlighting. My parser expected raw JSON.

Fix: Strip code fences before parsing.

import re
import json

def extract_json(text):
    match = re.search(r"```

(?:json)?\s*(.*?)\s*

```", text, re.DOTALL)
    if match:
        return json.loads(match.group(1))
    return json.loads(text)
Enter fullscreen mode Exit fullscreen mode

Verify: Feed it a fenced response. Confirm it parses.

Failure 3: The 429 Wall

Symptom: Day two. The bot stopped.

openai.RateLimitError: Error code: 429 - quota exceeded
Enter fullscreen mode Exit fullscreen mode

Diagnosis: I burned the free token quota in one night. The git log had 20 commits with long messages. Each call consumed thousands of tokens. I never checked the usage dashboard.

Fix: Truncate the input. Count tokens before sending.

log = subprocess.run(
    ["git", "log", "-5", "--format=%h %s"],
    capture_output=True, text=True
).stdout[:2000]
Enter fullscreen mode Exit fullscreen mode

Five commits. Two thousand characters. Enough for a useful summary.

Verify: Check the usage dashboard the next morning. Confirm the drop.

Failure 4: The OOM Kill

Symptom: The process vanished. No error in the log. Just a Killed line.

Diagnosis: The free server ran out of memory. The OOM killer targeted my Python process.

Fix: Limit memory. Keep the bot stateless.

ulimit -v 512000  # 512 MB virtual memory
Enter fullscreen mode Exit fullscreen mode

Read from disk. Write to disk. Do not hold data in memory.

Verify: Run dmesg | grep -i oom. Confirm no new kills.

Failure 5: The Timezone Trap

Symptom: The summary said "yesterday" when it meant "today".

TypeError: can't compare offset-naive and offset-aware datetimes
Enter fullscreen mode Exit fullscreen mode

Diagnosis: Git timestamps are timezone-naive. Python's datetime.now() on the server was timezone-aware. Comparing them crashed the script.

Fix: Force UTC everywhere.

from datetime import datetime, timezone

now = datetime.now(timezone.utc)
Enter fullscreen mode Exit fullscreen mode

Verify: Run the bot at 23:59. Confirm the date rolls over correctly.

Failure 6: The Cron Env Void

Symptom: Cron ran the job. The script failed. No output.

Diagnosis: Cron does not load your shell profile. The API key was not set.

Fix: Export variables inside the cron command.

0 23 * * * cd /home/user/bot && LLM_API_KEY=... LLM_BASE_URL=... LLM_MODEL=... /home/user/bot/venv/bin/python summarize.py >> bot.log 2>&1
Enter fullscreen mode Exit fullscreen mode

Verify: Check the log file. Confirm output appears.

Failure 7: Context Length Exceeded

Symptom: A 400 error.

openai.BadRequestError: Error code: 400 - context_length_exceeded
Enter fullscreen mode Exit fullscreen mode

Diagnosis: One commit message was enormous. A merge commit with a 3,000-word description. It pushed the total over the model's limit.

Fix: Cap each commit message.

commits = [c[:200] for c in commits]
Enter fullscreen mode Exit fullscreen mode

Verify: Send the longest commit. Confirm it fits.

What I Learned

Free infrastructure is not bad. It is just honest. It shows you every assumption you made about reliability.

  • Timeouts are real. Retry.
  • Models add formatting. Strip it.
  • Quotas run out. Count tokens.
  • Memory is limited. Keep it small.
  • Timezones lie. Use UTC.
  • Cron has no env. Set it explicitly.
  • Context has a ceiling. Trim early.

Who Should Not Do This

Do not run this for production. Do not send sensitive commit messages to a free model. Do not expect a free server to survive a traffic spike.

Use this setup for personal projects. Use it to learn. Use it to build a habit of observability.

Try It

Build a small bot. Break it on purpose. Read every error. Fix each one.

MonkeyCode's free tier is a good place to start. The dashboard shows current limits. The same code works with any OpenAI-compatible provider.

Start with one failure. Let the error log teach you the rest.

Top comments (0)