Fundamentals 19 min read

Effective Error Logging Practices and Common Causes of Software Errors

The article explains why clear, complete and consistent error logs are essential for troubleshooting, enumerates typical sources of bugs—from invalid parameters and integration failures to logic coupling and hardware issues—and provides concrete guidelines and code examples for writing diagnostic logs that are easy to understand and act upon.

Java Captain
Java Captain
Java Captain
Effective Error Logging Practices and Common Causes of Software Errors

How to Write Error Logs That Are Easy to Debug

The main goal of error logging is to provide reliable clues for troubleshooting, but in practice logs are often incomplete, ambiguous, or lack context, making debugging time‑consuming.

How Errors Are Generated

Errors usually originate from three layers:

Invalid parameters passed from upper‑level systems. These can be caught by input validation and pre‑condition checks.

Issues arising from interaction with lower‑level systems, which include: Successful processing but communication failure, leading to data inconsistency. A timeout‑compensation mechanism can record the task and correct it later. Successful communication but lower‑level processing failure. Coordination with the downstream team and handling error codes appropriately are required.

Errors produced within the current layer itself. Typical causes are: Negligence (e.g., using & instead of && , = instead of == , boundary mistakes). Static analysis and unit‑test coverage can mitigate this. Insufficient exception handling (e.g., missing input validation). Use regular expressions, thorough checks, and return clear error codes and messages. Tight logical coupling that makes local changes affect the whole system. Keep functions short (<50 lines), stateless, and interfaces orthogonal. Incorrect algorithms. Separate algorithms from business code and verify them with unit tests (sorting, encryption, etc.). Parameter order mistakes (e.g., modifyFlow(int rx, int tx) called as modifyFlow(tx, rx) ). Use strongly typed parameters. Null‑pointer exceptions. Ensure objects are initialized and null‑checked before use. Network communication errors caused by latency or blockage. Log INFO at both ends to obtain timing clues. Transaction and concurrency errors. Add INFO logs around shared‑state operations. Configuration errors. Log all configuration items at startup and verify they load correctly. Business‑knowledge gaps. Document business use‑cases, pre‑conditions, post‑conditions, and perform code reviews. Design flaws (e.g., synchronous vs. asynchronous trade‑offs, cache consistency). Write and review detailed design documents. Unknown‑detail bugs such as buffer overflows or SQL injection. Choose mature, well‑tested libraries and annotate POJOs with @JsonIgnoreProperties(ignoreUnknown = true) when needed. Time‑drift bugs (e.g., outdated encryption algorithms). Keep an eye on security advisories and update libraries promptly. Hardware‑related failures (memory leaks, OOM). Monitor CPU, memory, and network metrics.

Common Error Log Problems

Missing error parameters and content.

Unclear error scenario.

Vague or cryptic messages.

Lack of guidance for troubleshooting.

Insufficient detail about the root cause.

Half‑English sentences that are hard to read.

Examples of poor logs and their improved versions are shown below.

if ((storageType == StorageType.dfs1 || storageType == StorageType.dfs2) &&
    (zone.hasStorageType(StorageType.io3) || zone.hasStorageType(StorageType.io4))) {
    // enter dfs1/dfs2 with io3/io4 storage
} else {
    log.info("zone storage type not support, zone: " + zone.getZoneId() + ", storageType: " + storageType.name());
    throw new BizException(DeviceErrorCode.ZONE_STORAGE_TYPE_NOT_SUPPORT);
}

Improved log format:

log.error("[createNc] nc already exists, please check parameters. Given nc ip: " + request.getIp());

General log template:

log.error("[InterfaceName] [ErrorMessage] happens. Params: %s. Reason: %s. Suggested action: %s.");

Basic Principles for Writing Error Logs

Be as complete as possible – include scenario, cause, and suggested fix.

Be specific – indicate exact resources, IDs, or values involved.

Be direct – the log should immediately convey the problem.

Integrate known solutions into the log message.

Maintain a clean, uniform format.

Use unique keywords (timestamp, entity ID, operation name) for easy searching.

Typical Troubleshooting Steps

Login to the application server → Open the log file → Locate the error log entry → Follow the clues to identify, confirm, and resolve the issue.

When to Use Different Log Levels

INFO : Normal operational messages that help trace execution.

WARN : Minor issues that do not affect functionality.

ERROR : Serious problems that prevent the operation from completing.

By thinking carefully about what information will be most useful for future debugging and by following the guidelines above, developers can create error logs that serve both as immediate diagnostics and as valuable documentation for the system.

DebuggingJavasoftware developmentbest practicesError Logging
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.