Skip to content

Commit abe7283

Browse files
authored
fix: check mdState to determine array stopped during onboarding (#1969)
## Summary - **Fix onboarding wizard "array must be stopped" false positive during internal boot.** The `UpdateServerIdentity` mutation was checking only `fsState` (filesystem state) to determine if the array was stopped. During internal boot, the boot pool keeps `fsState` as `Started` even when the disk array (`mdState`) is `STOPPED`. Now checks `mdState === ArrayState.STOPPED` as the primary indicator, falling back to `fsState === 'Stopped'` for backward compatibility. - **Add regression test** for the internal boot scenario: `mdState=STOPPED` + `fsState=Started` should allow server name changes. - **Add `mdState` to existing test mock** so the "array running" test explicitly asserts against `mdState=STARTED`. ## Context Bug report: "Onboarding Wizard: says array is running when it isn't" — tested on 7.3.0-beta.1.2 with Connect 2026.03.25.2146. After booting into internal boot, the onboarding wizard incorrectly blocked server name changes because the boot pool kept `fsState` as `Started` even though the array was stopped. Root cause: The boot pool (ZFS pool used for internal boot) runs its own filesystem layer, keeping `fsState` as `Started`. The actual disk array state is tracked by `mdState`, which correctly shows `STOPPED`. ## Test Coverage ``` CODE PATH COVERAGE =========================== [+] server.service.ts — updateServerIdentity() array check ├── [★★★ TESTED] mdState=STARTED, name changed → throws ├── [★★★ TESTED] mdState=STOPPED, fsState=Started → allows (internal boot fix) ├── [★★★ TESTED] name unchanged → skips check └── [IMPLICIT] fsState=Stopped fallback → covered by existing tests COVERAGE: 4/4 paths (100%) ``` ## Pre-Landing Review No issues found. ## Test plan - [x] All API tests pass (174 files, 1966 tests) - [x] All Web tests pass (64 files, 618 tests) 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved server name change validation to correctly identify when an array is stopped, allowing name updates in more scenarios including during filesystem initialization. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent afe1ae6 commit abe7283

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

api/src/unraid-api/graph/resolvers/servers/server.service.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ describe('ServerService', () => {
8585
vi.mocked(getters.emhttp).mockReturnValue({
8686
var: {
8787
name: 'Tower',
88+
mdState: 'STARTED',
8889
fsState: 'Started',
8990
},
9091
} as any);
@@ -99,6 +100,24 @@ describe('ServerService', () => {
99100
});
100101
});
101102

103+
it('allows name change when mdState is STOPPED even if fsState is not Stopped (internal boot)', async () => {
104+
vi.mocked(getters.emhttp).mockReturnValue({
105+
var: {
106+
name: 'Tower',
107+
mdState: 'STOPPED',
108+
fsState: 'Started',
109+
regGuid: 'GUID-123',
110+
port: '80',
111+
comment: '',
112+
},
113+
networks: [{ ipaddr: ['192.168.1.10'] }],
114+
} as unknown as ReturnType<typeof getters.emhttp>);
115+
116+
await expect(service.updateServerIdentity('NewTower', 'desc')).resolves.toMatchObject({
117+
name: 'NewTower',
118+
});
119+
});
120+
102121
it('calls emcmd with expected params and returns optimistic server', async () => {
103122
const result = await service.updateServerIdentity('Tower', 'Primary host');
104123

api/src/unraid-api/graph/resolvers/servers/server.service.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { GraphQLError } from 'graphql';
44

55
import { emcmd } from '@app/core/utils/clients/emcmd.js';
66
import { getters } from '@app/store/index.js';
7+
import { ArrayState } from '@app/unraid-api/graph/resolvers/array/array.model.js';
78
import {
89
ProfileModel,
910
Server,
@@ -100,8 +101,10 @@ export class ServerService {
100101
}
101102

102103
if (name !== currentName) {
104+
const mdState = currentEmhttp.var?.mdState;
103105
const fsState = currentEmhttp.var?.fsState;
104-
if (fsState !== 'Stopped') {
106+
const arrayStopped = mdState === ArrayState.STOPPED || fsState === 'Stopped';
107+
if (!arrayStopped) {
105108
throw new GraphQLError('The array must be stopped to change the server name.');
106109
}
107110
}

0 commit comments

Comments
 (0)