Known‐Quirks‐and‐Caveats - Petewg/harbour-core GitHub Wiki

Harbour - Known Quirks and Caveats (and a few key tips for avoiding them)

Harbour is a mature xBase language with decades of real-world use in production systems.
While it is powerful and reliable, it has several characteristics that developers should be aware of,
especially when maintaining or modernizing legacy codebases.

Workareas and Aliases

Harbour relies heavily on implicit workareas.
Forgetting to explicitly SELECT the intended alias may result in operations
being performed on the wrong table, often without any runtime error.

Index Management

Indexes require careful handling:

  • Incorrect tag selection
  • Wrong order
  • Inconsistent RDD usage

Any of the above can cause SEEK operations to silently fail while the application continues running.

Variable Scope Rules

Variables default to global scope if LOCAL is omitted.
This can lead to unexpected side effects and hard-to-trace bugs caused by unintended variable sharing.

Weak Type Enforcement

Harbour performs implicit type conversions.
Values such as numbers and dates may silently become strings, requiring frequent manual
conversions (VAL(), CTOD(), DTOC()).

Concurrency and File Locking

File-based concurrency relies on record and file locks (RLOCK(), FLOCK()).
These mechanisms work reliably in controlled environments but can fail under network latency
or improper usage, often without clear diagnostics.

Silent Runtime Errors

Many logical errors do not raise exceptions.
The program may continue executing normally while producing incorrect results,
increasing debugging complexity.

Object-Oriented Limitations

Harbour supports OOP features, but with limitations:

  • Weak encapsulation
  • No strict interfaces
  • Public access to internal DATA members

This can lead to fragile designs if not carefully managed.

Global SET Commands

Global SET commands affect the entire runtime environment:

  • SET DELETED
  • SET DATE
  • SET CENTURY

A misplaced or forgotten SET can cause unpredictable behavior across the application.

Legacy Code Patterns

Long-lived codebases often contain large procedural constructs (e.g. extensive DO CASE blocks)
with minimal documentation, making maintenance difficult.


Best Practices

  • Always use explicit workareas and aliases
    Use SELECT <alias> consistently to avoid writing to the wrong table.

  • Declare all variables
    Use LOCAL or STATIC for variables to prevent accidental global variable collisions.

  • Manage indexes carefully
    Keep index tags, order, and RDD consistent. Regularly rebuild indexes if needed.

  • Handle types explicitly
    Avoid implicit conversions. Use VAL(), CTOD(), DTOC() where appropriate to ensure correct types.

  • Use file locking conscientiously
    Apply RLOCK() / FLOCK() with awareness of potential network latency and lock contention.

  • Document code and logic
    Comment DO CASE blocks, complex loops, and legacy routines. Future maintainers will thank you.

  • Limit global SET changes
    Reset SET commands to safe defaults when entering/exiting routines. Avoid permanent changes in shared modules.

  • Embrace modular design
    Split functionality into procedures, functions, and classes where possible, even with Harbour’s OOP limitations.

  • Test and validate thoroughly
    Because silent errors are common, always validate output and include automated checks if feasible.

  • Use version control
    Even for legacy Harbour projects, track changes and maintain backups — debugging old DBF/NTX systems
    without version history is painful.


Harbour remains stable and performant when used with care. Following these practices reduces common pitfalls
and makes legacy codebases more maintainable.


⚠️ **GitHub.com Fallback** ⚠️