Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Troubleshooting

This guide helps you diagnose and fix common issues when working with Qleany.


Generation Issues

Files aren’t being generated where I expect

When you click “Generate” and nothing appears in your project, first check the prefix_path in your manifest’s global section. This path is prepended to all generated file paths. If your manifest says prefix_path: src but your project expects files in source/, the files will be written to the wrong location.

In the UI, is the “in temp/” checkbox selected? If so, files are written to a temporary folder inside the Qleany application data directory, not your project folder. Uncheck it to write directly to your project. For a minimum of safety, this checkbox is checked by default at each launch.

Also, verify you’ve actually selected files to generate. The Generate tab shows all potential files, but only checked files are written. If you accidentally unchecked everything, clicking “Generate (0)” does nothing.

If using the CLI, double-check the --output flag points where you intend. A common mistake is specifying a relative path when you meant absolute, or vice versa.

Some files are missing after generation

Qleany generates files based on what’s defined in your manifest. If an entity is missing its controller and CRUD use cases, check that allow_direct_access isn’t set to false for that entity. Entities with allow_direct_access: false don’t generate files in the direct_access/ folder. This is intentional to hide some entities.

Entity marked by only_for_heritage: true skip all generation. They don’t produce any files and exist solely to be inherited from.

For C++/Qt, if you’re missing list models or single models, verify you’ve enabled list_model: true on the relationship field or single_model: true on the entity itself. These aren’t generated by default.

Generation succeeds but files are empty or truncated

This typically indicates a template error or an edge case in your manifest that the generator didn’t handle. Check that your entity and field names follow the expected conventions (PascalCase for entities, snake_case for fields). Unusual characters or reserved keywords in names can cause template rendering to fail silently.


Compilation Issues

“Module not found” or “File not found” after adding a new entity

When you add a new entity, several aggregate files need to be regenerated together. These files contain references to all entities, so adding one entity means updating them all. If you only regenerated the new entity’s files without updating the aggregate files, the compiler won’t find the new module.

For Rust, regenerate these files together: common/event.rs, common/entities.rs, common/direct_access/repository_factory.rs, common/direct_access/setup.rs, common/direct_access.rs, and direct_access/lib.rs.

For C++/Qt, regenerate: common/database/db_builder.h, common/direct_access/repository_factory.h/.cpp, common/direct_access/event_registry.h, common/direct_access/CMakeLists.txt, common/entities/CMakeLists.txt and direct_access/CMakeLists.txt.

See Regeneration Workflow for the complete list.

Compilation errors after renaming an entity

Qleany doesn’t track renames. If you renamed Car to Vehicle in the manifest and regenerated, you now have both sets of files — the old Car files still exist and may conflict with the new Vehicle files.

Delete the old entity’s files manually. Search your codebase for any remaining references to the old name and update them. Then regenerate the aggregate files mentioned above.

Type mismatch errors in generated code

This usually happens when your manifest has inconsistent relationship definitions. For example, if Entity A declares a one_to_many relationship to Entity B, but Entity B doesn’t exist, the generated code may have type mismatches.

Review your relationship definitions. Every many_to_one or many_to_many relationship should reference an entity that exists and is owned by another entity.

Enums names and entities names must not conflict. If you have an enum named Status and an entity named Status, the generated code will have type conflicts. Rename one of them.


Undo/Redo Issues

Undo affects unexpected entities

This is the classic symptom of violating the undo-redo inheritance rules. If an undoable parent owns a non-undoable child through a strong relationship, undoing the parent can cascade to the child unexpectedly.

Check your entity tree. Every entity under an undoable parent (via strong relationships) must also be undoable. If you have data that shouldn’t participate in undo (settings, caches, temporary state), place it in a separate non-undoable trunk — don’t nest it under undoable entities.

The GUI can generate a Mermaid diagram of your entity tree. This can help visualize the relationships and ensure they align with your undo/redo requirements.

See Undo-Redo Architecture for the complete rules and recommended configurations.

Undo/redo does nothing

First, verify the entity’s controller was generated with undo support. Check that undoable: true is set on the entity in your manifest. If it’s false or omitted, the generated controller won’t include undo/redo infrastructure.

For custom use cases, check that undoable: true is set on the use case definition in the features section. Non-undoable use cases don’t generate command scaffolding.

If undo is enabled but still doesn’t work, verify the undo system is properly initialized. In C++/Qt, the UndoRedoSystem must be instantiated at startup and given to ServiceLocator before any undoable operations. In Rust, it’s similar and depends on each UI, but the instance must be created and passed to controllers.

Redo recreates entities with wrong IDs

This can happen if your undo implementation doesn’t properly store and restore entity IDs. The generated entity’s CRUD use cases store the created ID during execute() and uses it during undo(). If you’ve modified the generated command code, ensure you’re preserving IDs correctly.

In custom feature/use cases, check the execute() and undo() methods to ensure IDs are being preserved.


Database Issues

“Database locked” errors (C++/Qt SQLite)

SQLite allows only one writer at a time. If you see “database is locked” errors, you likely have multiple threads trying to write simultaneously, or a long-running read transaction is blocking writes.

Use the generated DbSubContext for all database operations — it manages transactions properly. Don’t hold transactions open longer than necessary. For long operations, consider breaking them into smaller transactions.

The generated code uses WAL mode, which improves concurrency, but writers still block each other. If you need truly concurrent writes, you may need to queue operations through a single writer thread.

Data doesn’t persist between sessions

Remember that Qleany’s internal database is ephemeral by design. It lives in a temporary location and serves as a working cache, not permanent storage. Your application is responsible for saving data to a user file (JSON, XML, your own SQLite file, etc.) and loading it back.

If you expected the internal database to persist, review the Generated Infrastructure - C++/Qt documentation. The pattern is: load file → populate internal database → work → save to file.

Cache returns stale data

The generated table caches expire after 30 minutes and invalidate on writes. If you’re seeing stale data, check whether writes are going through the proper repository methods. Direct SQL queries that bypass the repository won’t invalidate the cache.

Also, verify you’re not holding onto old entity instances after they’ve been updated. Fetch fresh data from the repository after any operation that might have modified it. Use events/signals to notify UI components when data changes.


QML Integration Issues (C++/Qt)

List model doesn’t update when entities change

The generated list models subscribe to entity events through the EventRegistry. If updates aren’t appearing, verify that the EventRegistry signals are being emitted. Check that the entity’s repository calls emit m_events->updated(id) after modifications.

If events are firing but the model doesn’t update, ensure the model instance is still alive. Creating a new model instance on each navigation might discard the old subscriptions. Declare models at the component level, not inside functions.

Single model shows stale data

Single{Entity} fetches data when itemId changes. If you set the same ID again, it won’t refetch. To force a refresh after knowing the entity changed, you can toggle itemId to -1 and back, or connect directly to the entity’s updated signal and call a refresh method.

QML mocks work but real backend doesn’t

The mocks are JavaScript stubs that return fake data immediately. The real backend is asynchronous and may have different timing. If your QML code assumes synchronous data availability, it will work with mocks but fail with the real backend.

Also check that you’ve correctly switched build configurations. The YOUR_APP_BUILD_WITH_MOCKS CMake option controls whether mocks or real implementations are used. Ensure it’s set to OFF for production builds.


Rust-Specific Issues

“Cannot borrow as mutable” in generated code

The generated Rust code uses specific borrowing patterns. If you’ve modified the generated code and introduced borrow checker errors, review whether you’re trying to mutate while borrowing. Nothing new here.

The generated repositories take &mut self for write operations and &self for reads. Make sure you’re not trying to read and write simultaneously through the same repository instance. The architecture uses the Rust type system to enforce the difference between read and write operations.

Long operation never completes

If a long operation hangs, check that you’re properly awaiting or polling the handle. The LongOperationManager spawns work on a separate thread, but you must check for completion.

Also, verify the operation itself doesn’t have an infinite loop. Add progress reporting (progress.set_percent()) at key points so you can see where it stalls.

Events not received

The Rust event system uses channels. If you’re not receiving events, verify you’ve subscribed before the events were published. Events published before subscription are lost.

Also check that you’re actually polling the receiver. In synchronous code, call rx.recv() or rx.try_recv(). If using async, ensure the receiver task is being polled. Check crates/slint_ui/src/event_hub_client.rs of Qleany repository for an example.


Manifest Issues

“Invalid manifest” error on load

The manifest parser is strict about YAML syntax. Common issues include incorrect indentation (YAML uses spaces, not tabs), missing colons after keys, or unquoted strings that look like other YAML types.

Validate your YAML syntax with an online validator or yamllint before loading in Qleany. The error message should indicate the line number where parsing failed.

Relationship validation fails

Certain relationship configurations are invalid and rejected at parse time. For example, strong: true is only valid on one_to_one, one_to_many, and ordered_one_to_many relationships — not on many_to_one or many_to_many. The optional flag only applies to one_to_one and many_to_one.

See the validation rules table in Manifest Reference.

Changes to manifest don’t appear after regeneration

You may have generated in the temp folder. There is a checkbox in the UI to toggle between temp and project folders.


Getting Help

If you’ve worked through this guide and still have issues, open an issue on GitHub: github.com/jacquetc/qleany/issues

Include in your issue:

  • What you were trying to do
  • What you expected to happen
  • What actually happened
  • Relevant portions of your manifest (sanitize any private information)
  • Error messages or unexpected output
  • Qleany version and target language (Rust or C++/Qt)

Response times may vary, but thoughtful, well-documented issues are more likely to get attention. If you’re a FernTech customer, please contact support for priority assistance.