04. Initial Development

Write Helpful Errors Before Your Project Grows

Set up clear errors, logs, and recovery hints early so new contributors can debug problems without knowing the whole codebase.
Table of Contents
In: 04. Initial Development

In early development, it is tempting to focus only on the happy path: the form submits, the API returns data, the page loads. That is understandable. You are trying to prove the idea works.

But open source projects built for public benefit need more than working code. They need code that another person can understand when something breaks. Clear errors and useful logs make your project easier to run, easier to contribute to, and easier to trust.

This is especially important for projects in education, accessibility, security, and civic or social impact. The people using the software may not have paid support, and the people helping maintain it may be volunteers. A helpful error can save hours of guessing.


Start With the First Failure

Before your project has many features, choose one failure path and make it excellent. This is a good initial development habit because it shapes how the rest of the codebase handles problems.

Pick a common failure, such as:

  • A missing environment variable
  • A database connection failure
  • An invalid uploaded file
  • A third-party service being unavailable
  • A user entering data in the wrong format

Then ask: if a new contributor sees this failure, will they know what happened and what to try next?

A weak error says: Something went wrong.

A better error says: Missing DATABASE_URL. Create a .env file from .env.example, then run npm run dev again.

The second version teaches the project while reporting the problem. That is the goal.


Create a Small Error Pattern

You do not need a complex error framework at the beginning. You need one simple pattern that contributors can copy.

A useful application error usually has:

  • A short name: what kind of problem happened
  • A clear message: what the developer or user needs to know
  • A safe cause: enough detail for debugging without exposing secrets
  • A next step: what to check or change

For example, an education project that imports student reading lists from CSV files might use an error like this:

  • Name: InvalidCsvHeader
  • Message: The uploaded CSV is missing the required column “title”.
  • Cause: Headers found: author, grade_level, url
  • Next step: Add a “title” column or download the sample CSV template.

This helps the user, but it also helps the contributor who is trying to improve the import feature. They can see the expected shape of the data without digging through every parser function.


Separate User Messages From Developer Details

Beginner-friendly does not mean dumping every technical detail onto the screen. A learner, teacher, community organizer, or assistive technology user should not have to read a stack trace to understand what to do.

Use two layers when possible:

  • User-facing message: plain language, no secrets, no internal jargon
  • Developer-facing detail: logs, error codes, file names, request IDs, or safe debugging context

For example, a public accessibility tool that converts documents into more readable formats might show the user:

We could not process this file. Please try a PDF under 25 MB or contact the project maintainers with error code FILE_TOO_LARGE.

The log might include:

FILE_TOO_LARGE: upload rejected. size_mb=42 max_mb=25 route=/convert

The user gets a clear next step. The maintainer gets enough information to debug. No one sees private file contents, tokens, or unnecessary personal data.


Make Logs Boring and Searchable

Logs are most useful when they are predictable. During initial development, choose a few conventions and write them down in the project README or a short developer note.

Good logs are:

  • Consistent: similar events use similar wording
  • Searchable: include stable error names or codes
  • Safe: do not include passwords, tokens, private messages, or sensitive records
  • Useful: include the action being attempted and the part that failed

A weak log says:

failed

A better log says:

IMPORT_CSV_FAILED: missing required header “title” file_type=text/csv

You do not need to log everything. In fact, too many noisy logs make debugging harder. Start with important boundaries: app startup, configuration loading, file import, authentication, external services, and background jobs.


Add Recovery Hints Near the Code

When a contributor finds an error in the code, they should also find the likely fix nearby. This does not require long comments everywhere. It means placing short, practical hints where failure is expected.

Helpful places for recovery hints include:

  • Validation functions
  • Configuration loaders
  • File parsers
  • API clients
  • Permission checks
  • Data migration scripts

For example:

If this fails locally, confirm that .env was copied from .env.example and that the database container is running.

That one sentence can help a first-time contributor fix the problem without opening an issue or waiting for a maintainer. It also reduces repeated support work for the project.


Use Error Names as Contributor Clues

Error names are part of your project vocabulary. Choose names that describe the real problem, not just the technical symptom.

Instead of:

  • BadRequest
  • ServerError
  • Failure
  • Exception

Use names like:

  • MissingRequiredProfileField
  • UnsupportedDocumentFormat
  • LessonPlanNotFound
  • PasswordResetTokenExpired

Specific names help contributors search the codebase, tests, issues, and logs. They also make the project easier to discuss. A maintainer can say, “This pull request fixes UnsupportedDocumentFormat for scanned PDFs,” and reviewers immediately understand the area of work.


Keep Security and Privacy in Mind

Helpful errors should not leak sensitive information. This matters for all open source projects, but especially for tools that serve students, disabled users, community groups, or people facing security risks.

Avoid putting these in user messages or public logs:

  • Passwords, tokens, API keys, or session IDs
  • Full personal records
  • Private file contents
  • Exact permission rules that would help an attacker
  • Database connection strings

When in doubt, log the type of thing that failed, not the private value itself. For example, log user_id_present=true instead of logging an email address. Log token_missing instead of the token value.

This habit supports sustainability. Maintainers should not have to clean secrets out of bug reports, screenshots, or shared logs later.


Write One Error Checklist for Pull Requests

You can make this easy for future contributors by adding a small checklist to your pull request template or contributor notes.

For any new feature, ask:

  • What can fail?
  • Will the user see a plain-language message?
  • Will the developer have a safe log or error code?
  • Is there a next step or recovery hint?
  • Are secrets and private data kept out of errors?
  • Can a new contributor search for this error by name?

This keeps the standard visible without turning it into a heavy process. The point is not perfection. The point is to help every new piece of code be easier to understand than the last.


TL;DR

Helpful errors are part of a beginner-friendly codebase. They reduce confusion, lower the support burden, and make open source projects easier to sustain.

  • Start by improving one common failure path.
  • Use clear error names, plain messages, safe details, and next steps.
  • Separate user-facing messages from developer logs.
  • Keep logs consistent, searchable, and privacy-safe.
  • Add short recovery hints near code that commonly fails.
  • Use a small pull request checklist so contributors follow the pattern.

Software for Progress Foundation supports open source developers building tools that benefit all people. Clear errors are a small technical choice that supports that mission: they help more people understand, use, fix, and sustain the software.

Written By
Cory Fail
Cory Fail leads the Software for Progress Foundation, helping developers build Open Source tools for education, accessibility, and social good through mentorship and community support.
Comments
More From Software for Progress Foundation
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Software for Progress Foundation.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.