{"record":{"id":"a5522c8c63c4e340","repo":"linera-io/linera-protocol","slug":"there-are-owners-but-weights","errorCode":null,"errorMessage":"There are {} owners but {} weights.","messagePattern":"There are (.+?) owners but (.+?) weights\\.","errorType":"validation","errorClass":"async_graphql::Error","httpStatus":null,"severity":"error","filePath":"linera-service/src/node_service.rs","lineNumber":515,"sourceCode":"            default = 10_000\n        )]\n        base_timeout_ms: u64,\n        #[graphql(\n            desc = \"The number of milliseconds by which the timeout increases after each \\\n                    single-leader round\",\n            default = 1_000\n        )]\n        timeout_increment_ms: u64,\n        #[graphql(\n            desc = \"The age of an incoming tracked or protected message after which the \\\n                    validators start transitioning the chain to fallback mode, in milliseconds.\",\n            default = 86_400_000\n        )]\n        fallback_duration_ms: u64,\n    ) -> Result<ChainId, Error> {\n        let owners = if let Some(weights) = weights {\n            if weights.len() != owners.len() {\n                return Err(Error::new(format!(\n                    \"There are {} owners but {} weights.\",\n                    owners.len(),\n                    weights.len()\n                )));\n            }\n            owners.into_iter().zip(weights).collect::<Vec<_>>()\n        } else {\n            owners\n                .into_iter()\n                .zip(iter::repeat(100))\n                .collect::<Vec<_>>()\n        };\n        let multi_leader_rounds = multi_leader_rounds.unwrap_or(u32::MAX);\n        let timeout_config = TimeoutConfig {\n            fast_round_duration: fast_round_ms.map(TimeDelta::from_millis),\n            base_timeout: TimeDelta::from_millis(base_timeout_ms),\n            timeout_increment: TimeDelta::from_millis(timeout_increment_ms),\n            fallback_duration: TimeDelta::from_millis(fallback_duration_ms),","sourceCodeStart":497,"sourceCodeEnd":533,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-service/src/node_service.rs#L497-L533","documentation":"The `openMultiOwnerChain` GraphQL mutation creates a chain owned by several accounts with optional weighted voting. When `weights` is provided it must contain exactly one u64 per entry of `owners`; a length mismatch fails validation before anything is submitted on-chain. Without `weights`, every owner gets weight 100.","triggerScenarios":"Calling `openMultiOwnerChain(owners: [a, b, c], weights: [100, 100])` — three owners but two weights, or vice versa; building the two arrays from separate loops that got out of sync.","commonSituations":"Frontend forms that collect owners and weights in separate lists; scripts that copy an owners array but edit the weights array; partial updates adding an owner without a weight.","solutions":["Make `weights.length === owners.length` before sending, or omit `weights` entirely for uniform weight 100.","Build (owner, weight) pairs in one place and unzip them into the two mutation arguments.","Validate the pair arrays in the UI/DTO layer so a mismatch can never reach the mutation."],"exampleFix":"// before\nconst owners = [u1, u2, u3], weights = [100, 100];\nawait gql.openMultiOwnerChain({ owners, weights }); // 'There are 3 owners but 2 weights.'\n\n// after\nconst pairs = [[u1, 100], [u2, 100], [u3, 100]];\nawait gql.openMultiOwnerChain({ owners: pairs.map(p => p[0]), weights: pairs.map(p => p[1]) });","handlingStrategy":"validation","validationCode":"if (weights && weights.length !== owners.length) throw new Error(`owners (${owners.length}) and weights (${weights.length}) must have equal length`);","typeGuard":"function isValidOwnerWeights(owners: unknown[], weights: unknown[] | null | undefined): boolean { return weights == null || (Array.isArray(owners) && Array.isArray(weights) && weights.length === owners.length); }","tryCatchPattern":"try { await gql.openMultiOwnerChain({ owners, weights }); } catch (e) { if (/owners but .* weights/i.test(e.message)) { /* fix arrays and resubmit */ } else throw e; }","preventionTips":["Build (owner, weight) pairs in one structure and derive both arrays from it.","Omit weights entirely for uniform weight 100.","Validate array lengths at the form/DTO boundary."],"tags":["node-service","graphql","multi-owner-chain","input-validation"],"backgroundTag":"array-length-mismatch","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}