- I ignored a great big warning sign up-front ("our previous developer abandoned the project, refusing to work with us again")
- I offered fixed-price (a horrible mistake for a variety of reasons, including that it was explicitly a 'learning project' for all of us)
- I didn't mitigate scope creep ("I know we said we'd hire a designer, but can you style the UI as well?")
- when we ran into obvious deadline and quality issues, I should have fixed it by re-evaluating things with the client; instead, I tried to "work harder"
- finally, when everything went south and the client refused to pay (and in fact demanded their deposit back!) I didn't take them to court for the money they owed me
All in all it was a horrible engagement for everyone involved, but a great learning experience for me at least. I hope the clients (quite reasonable people I think, just as domain-clueless as I was at the time) learned from it too.
Don't give up though. I continued contracting, and used those experiences to build a simple set of practices that made future engagements a lot more pleasant and productive for everyone involved. One of these is to be super-explicit up-front about how bugs are tracked, resolved and billed.
Something to consider: as a software professional, part of your job is to help your clients learn how to engage software professionals. Many clients are either new to the field, try to bring odd expectations from other fields into it, or have been burned by bad engagements in the past and are 100% in CYA mode. Help them get past that :)