Common mistakes
This page collects the mistakes developers hit most often when building Comind apps. Each entry explains what goes wrong, why it happens, and the correct approach.
Importing settings instead of reading them at runtime
Using a static import for workspace settings bakes the compile-time value into the bundle. The app then ignores the per-workspace override entirely. Use ComindView.getVars() (client-side) or ComindServer.getVars() (server-side) at runtime to retrieve the value the workspace administrator actually configured. See Settings model for the full runtime API.
Forgetting the c_ prefix on custom fields
System fields provided by @comind/base - title, description, state - have no prefix. Every field you add must use the c_ prefix: c_priority, c_due_date, and so on. Omitting the prefix causes silent lookup failures because the runtime searches the wrong field namespace. See Fields for naming rules.
Misunderstanding plugin merge order
Plugins are composed with a deep-merge strategy, and the last plugin in the chain wins. Arrays replace rather than concatenate. If two plugins define a field with the same name, the later definition overwrites the earlier one. Audit merge order explicitly and test the resulting schema whenever you add or reorder plugins. See Plugins for composition details.
Changing a parent app without checking its children
inheritFrom creates a live link - every child app inherits the parent's fields, actions, and layouts. A change to the parent propagates to all children on the next install. Always test parent changes across every inheriting app before deploying. See Plugins for the inheritance model.
Treating calculated fields as always synchronous
Simple calc fields resolve synchronously during save. Rollups and table-calcs do not - they are processed asynchronously by the background Processor. The UI uses a custom refresh mechanism rather than real-time push. If your logic depends on a rollup result being available immediately, it will read stale data. Design actions and visibility rules to account for the async delay. See Fields for calc field types.
Confusing push and install
The push command uploads source code to the server. The install command compiles and deploys it. Pushing without installing leaves the running app unchanged. Also verify you are targeting the correct branch - deploying to main when you intended prod, or vice versa, is a common source of unexpected behavior. See CLI reference for the full command list.
Overlapping permission layers
Record-level ACL and field-level permissions are evaluated independently, and combining them can produce surprising results. Evaluation order is workspace, then app, then record, then field. A field-level restriction can hide data even when the record-level ACL grants access. Map out permission layers before you mix ACL types.
Too many calculated fields
Each calc field that depends on another calc field creates a chain of recalculations. Large chains slow down saves and can cascade through rollups across related apps. Keep calc depth shallow and avoid circular dependency patterns. The e-grid Angular view also caps rendering at roughly 50 rows, so heavy calc usage compounds performance limits in list views.
Using React patterns in TSX layouts
Layout .tsx files look like React components but they are not. They compile to XML strings through the custom entity factory. React hooks, state management, and lifecycle methods are unavailable and will fail silently or throw at compile time. Treat layout files as pure template functions that return markup. See Form layouts for the correct authoring pattern.
Exposing secrets through static imports
A static import bundles the value into client-side JavaScript, making it visible in the browser. Store secrets in settings/secrets.ts and use COMIND_SECRET_* environment variables. The runtime injects these values on the server only. See Settings model for the secrets workflow.
Assuming action logic runs in the browser
Action logic executes on the C# backend through the Jint JavaScript engine, not in the browser. Browser-only APIs like fetch, document, and window are unavailable. Node-only modules are also unsupported. Write action logic using the server-side globals Comind provides. See Actions and Server-side API for the available runtime surface.