Troubleshooting — Installation¶
Problems standing up a new environment and getting its first users working. The procedure itself is in Installation; this page covers what goes wrong with it.
Startup fails¶
dotnet run, or the first request to IIS, fails before any page renders.
| Error | Cause | Fix |
|---|---|---|
Null in Startup. |
The Storage section is missing. Startup reads Storage while registering S3. |
Add the whole section — see Configuration. |
Sql — cannot open database, or login failed |
A connection string is wrong, or a database does not exist. | Check Hr, Ware and Hangfire. All three databases must exist. |
| Hangfire error at startup | The Hangfire database does not exist. Hangfire creates its schema (Prepare) but not the database. |
CREATE DATABASE for the Hangfire store, then restart. |
A wrong AWS key does not stop startup. The S3 client is built on first use, so bad credentials show up at the first upload or download instead. Under IIS, a startup failure appears as HTTP 500.30 — see Deployment for how to read it.
Nobody can sign in¶
On a freshly migrated database this is expected. Migrations create schema only: there is no seed data, no bootstrap script and no self-registration (R5-1). Use Route A or Route B.
If you took Route B (inserting the rows by hand) and sign-in still fails:
| Symptom | Cause | Check |
|---|---|---|
Invalid object name 'Asp in your script |
The users table is dbo.; On remaps it. |
Insert into Application. |
| "Wrong username or password" with the right password | The hash is not BCrypt. Application replaces the Identity hasher with BCrypt. |
Generate the hash with BCrypt at work factor 12. |
| The same message, and the hash is right | Application, so the password is never accepted. |
SELECT Is |
Null in Account |
There is no visible App row for this login: it is missing, or has Status < or Is, so the global query filter hides it. Login then dereferences it without a null check (R6-8). |
SELECT User must return 1 and 0. |
| Sent to Security to change the password | Is. |
Expected. Change it, or insert 0. |
Wrong passwords never lock an account
Login checks the password with CheckPasswordAsync, which does not increment the failure
counter, so lockout never engages (R6-7). Each failure on a known user sends that user a
"Security Alert" e-mail (R6-2), if mail is working.
Signed in, but every page is unauthorised¶
The user reaches the layout, but the top menu is empty and gated pages redirect to
/Error/UnAuthorised. Permission keys are re-read from the database on every request, so the
cause is always in these rows:
| Check | Why |
|---|---|
Application |
When 0, Permissions returns an empty key list: the user stays signed in but can open nothing. |
An App row with Is |
A disabled membership contributes no keys. |
App rows linking that group to App rows |
The group needs the keys themselves; 219 are in force. |
The spelling and case of App |
The gate compares keys case-sensitively; the menu compares them case-insensitively (R8-3). A key stored with different case shows the menu item and then refuses the page. |
If a user has the keys but their data scope for an area is Default, the screen opens with an
empty list. That is data scoping, not a failure — see
Permissions.
General Settings crashes¶
On a new database, /Admin/GeneralSettings shows a NullReferenceException, and saving reports
"Operation Failed!".
Bsettings expects 21 CommonSetting rows to exist already and never inserts them.
GetSettings reads them by list position, and SaveSettings updates them by SettingId
(R5-5). Insert them by SQL in this order, so the identity column assigns ids 1–21:
| Id | Setting | Id | Setting | Id | Setting |
|---|---|---|---|---|---|
| 1 | Cash box | 8 | Director approval | 15 | IT manager |
| 2 | Timesheet FO | 9 | HR approval | 16 | Project focal points (JSON) |
| 3 | Timesheet payer | 10 | Travel FO | 17 | Administration manager |
| 4 | Emergency cash box | 11 | Payroll allocator | 18 | Complaint admin |
| 5 | RFQ allower | 12 | Finance data officer | 19 | Supply-chain manager |
| 6 | E-mail service on/off | 13 | Travel safety officer | 20 | HR manager (saved, never read) |
| 7 | Procurement manager | 14 | ips — attendance allow-list |
21 | Compliance admin |
SettingName and SettingValue are both NOT NULL. Row 14 must be named ips, because it is also
looked up by name. Row 6's value must be True or False. Once the rows exist, set the real values
from the screen.
Row 6 controls all e-mail
Until row 6 exists and is True, no e-mail is sent at all — see
Integrations.
Approvals go nowhere¶
A request is submitted but appears in nobody's queue, or keeps waiting on someone who has left.
Approval chains resolve the next approver from four sources. When a lookup finds nobody, no error is raised; the document just has no usable approver.
| Approver | Resolved from | Common cause of "nobody" |
|---|---|---|
| HR manager, finance manager, general manager, supply-chain director | Whoever holds a position named exactly HR and Admin Manager, Finance Manager, General Manager or Supply Chain Director (R6-10) |
The position was renamed or spelt differently, or two positions share the name — the lookup uses Single and swallows the error. The "HR Manager" field in General Settings has no effect here. |
| Line manager | App on the requester's employee record, set in / |
Not set; or it still points to someone who has left. Nothing re-points it, so requests keep routing to the old manager. |
| Branch manager, HR, finance, logistics, treasury, accounting | The branch record, set at / |
Not set for the requester's branch. |
| Allocator, procurement manager, HR approval, director approval, timesheet and travel officers | General Settings rows | The row is missing, or holds the id of someone who has left. |
After fixing the data, re-point open documents with Refresh Next users at
/Admin/TriggerNextUser, choosing All. If anyone has run it for a single type since the last
restart, only that type is refreshed until the app pool recycles (R8-11), so recycle first if
in doubt.
Some approvals also need the approver to have an approved e-signature: procurement, warehouse,
leave, advance and overtime approvals check BSign.HasSign, and so does check-in from the home
page. An approver without one is refused at that step.