DEV Community

Cover image for The Bugs I Didn't Write And The Assumptions That Caused Them
Liatmoss
Liatmoss

Posted on

The Bugs I Didn't Write And The Assumptions That Caused Them

This week I accidentally created my first vibe coded application. You might ask how one does this accidentally, but it's actually easier than you think.

Assumptions Made:

The first mistake I made was to assume that Claude remembered my setup and how I like to pair program. I have only had one previous project coded with the help of Claude and GHCP and it's a much more basic application than what I was building this week.

I assumed, incorrectly, that Claude would 'remember' how I liked to work and go through the project with me as we make decisions and coding blocks together.

The other assumption I made was giving a somewhat blanket approval for Claude to just run with things. I thought at some point Claude would stop, check its understanding during development and then continue but I got excited at the idea of using subagents and once I'd selected that option there was no stopping Claude on its rampage through my code!

So What's the Project?

I've recently started looking at doing more work with AI rather than just prompting Claude or GHCP to help with the day to day. I wanted to actually call an LLM and sift through information which could then be saved in a DB and recalled at a later point.

I set myself a four week plan (with the help of Claude) to help solidify my learning with week one being a basic console application in C# that takes some text, sends to an LLM and then extracts certain information, in this case names of people, which is saved into a Postgres database.

Sounds simple right?

Where things went right

This project started off very interesting. I had a conversation with Claude, same as I would with another developer, about the right LLM to use for this project. We went through the positives, negatives and the potential cost benefits and pitfalls of each option.

In the end it was narrowed down to two choices, OpenAI or Gemini. Given that I was experimenting quite a bit and I didn't want to accidentally run up costs, I decided to go with Gemini's free tier for the moment with the option to move on and change later on down the line.

The other part that went well was the specs and the plans that were created. I input my four week plan into Claude and mentioned that I wanted to start week one first in its own separate folder within the repo so that it could run independently of project 2 which would be a combination of the following weeks and a more detailed project using larger inputs, Mediatr and authentication.

I utilised the /superpowers skill to create the spec and then the plan and during that time Claude asked me questions and grilled me on what exactly it was that I wanted to build. We also went through the environment variables that needed to be created to set up Gemini and Postgres and the safest way to do that so that the keys wouldn't end up on Github.

This back and forth conversation was a good start and really what I was hoping to continue throughout the project.

The bugs I didn't write

If we started off so well, how did we end up with a vibe coded app that took me longer to debug than it did to build?

I'm calling these issues bugs, but really they were just parts of the functionality that I wasn't expecting. Nothing was really broken, the code worked fine, I just didn't particularly understand it and there were some features that I wanted to appear differently.

  • The input string: The initial version of this application had a hard coded paragraph as part of the implementation. This really wouldn't have been an issue except that I was saving my extraction into a database to help with testing. Having the same paragraph appearing multiple times, even though it was sequential, made debugging difficult as I couldn't be sure if the latest entry was the same one that I was trying to test.

I ended up making a manual change here, with some input from Claude, to include a user prompt to input a paragraph. This way I was able to test different scenarios like what happens if the same name appears twice in the same input or what if there are no names in the input at all.

  • Gemini updates: The original vibe coded application hard coded a model choice into the Gemini URL.

var geminiUrl = $"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={geminiApiKey}";

This caused a problem midway through testing when the model that the API was calling was retired and no longer available. This was very unexpected and probably would have happened regardless of the application being vibe coded but it was something that I hadn't thought to check in the Gemini docs. I wasn't aware of what models I was utilising or calling or even which of the Gemini models were available to me.

After some back and forth conversation, I ended up adding a new environment variable that lets me choose which model to use.

using var httpClient = new HttpClient();
var geminiModel = Environment.GetEnvironmentVariable("GEMINI_MODEL") 
?? "gemini-flash-latest";

var geminiUrl = $"https://generativelanguage.googleapis.com/v1beta/models/{geminiModel}:generateContent?key={geminiApiKey}";
Enter fullscreen mode Exit fullscreen mode

I'm sure there are better ways around this which I will be exploring in my more in-depth project that will start in a few days.


Key Takeaways:

This application was all about learning and while it wasn't the learning I expected, there was a lot that I took away from this.

The first being don't just let the agent or subagents run! Question everything and bring them back to you if they're going rogue. I've now got an instructions doc in place which will hopefully allow for more back and forth pair programming for the next part of the project.

I also have some learning around LLMs and how they work and it's not the detailed knowledge of how to call and deserialise information. I now understand how model choices work in the URL call and what to change should we receive another error like what I was seeing yesterday when running my code locally.

When it comes to AI we should always trust but verify and I'm happy that I took that advice on board and actually made sure I knew what the code was meant to do before making any commits and approving the PR. I ran manual tests and found code that both wasn't what I was expecting and wasn't what I wanted. I found actual bugs and talked through how to fix them.

And most importantly, I learnt that a planning document isn't enough. Instruction files are invaluable, not just for your AI to know how your project works and details about setup but to instruct on how you want to work if you're happy with AI running on its own or if you want to be part of the decision making processes and pair program the whole way through.

Top comments (0)