From c7ce39d8ae81a7d07a19d22e40ac556504b3f511 Mon Sep 17 00:00:00 2001 From: Kevin Adams Date: Sun, 31 May 2026 08:58:00 -0400 Subject: [PATCH] fix: SCALE 25.10 strict Pydantic rejects volsize encoded as string (#269) SCALE 25.10 (Goldeye) enforces strict integer validation. The log call preceding the API call stringifies $size_b (sets Perl's POK flag), causing JSON::XS to encode it as "8589934592" (quoted) instead of 8589934592. int() at the encode site produces a fresh IV without the POK flag. Also adds error parser support for SCALE 25.10's field-keyed validation error format so the full Pydantic detail surfaces in PVE task logs. Co-Authored-By: Claude Sonnet 4.6 --- perl5/PVE/Storage/Custom/TrueNAS.pm | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/perl5/PVE/Storage/Custom/TrueNAS.pm b/perl5/PVE/Storage/Custom/TrueNAS.pm index b9aebca..4dbd0ed 100644 --- a/perl5/PVE/Storage/Custom/TrueNAS.pm +++ b/perl5/PVE/Storage/Custom/TrueNAS.pm @@ -193,6 +193,15 @@ sub _api { # SCALE 25.04+ returns Pydantic validation errors as an array my @msgs = map { $_->{message} // $_->{msg} // '' } @$body; $detail = " — " . join('; ', grep { length } @msgs); + } elsif (ref $body eq 'HASH') { + # SCALE 25.10+ returns field-keyed validation errors: { "field": [{message}...] } + my @msgs; + for my $field (sort keys %$body) { + my $errs = $body->{$field}; + next unless ref $errs eq 'ARRAY'; + push @msgs, map { "$field: " . ($_->{message} // '') } @$errs; + } + $detail = " — " . join('; ', grep { length } @msgs) if @msgs; } }; my $msg = "TrueNAS API $method $path: " . $res->status_line . $detail; @@ -435,15 +444,18 @@ sub alloc_image { my $prefix = _zvol_prefix($scfg); my $zvol = "$prefix/$name"; - my $size_b = $size_kb * 1024; + my $size_b = int($size_kb) * 1024; _log('info', "alloc_image: creating zvol $zvol ($size_b bytes) for VM $vmid"); # 1. Create the zvol + # int() here produces a fresh IV — string interpolation in the log call above + # sets Perl's POK flag on $size_b, which causes JSON::XS to encode it as a + # string. SCALE 25.10 strict Pydantic rejects string-typed integers. _api($scfg, 'POST', '/pool/dataset', { name => $zvol, type => 'VOLUME', - volsize => $size_b, + volsize => int($size_b), sparse => JSON::true, });