Skip to content

fix: store config/pipeline hashes as int64 to fit the uint32 range (#232)#233

Merged
aa1ex merged 1 commit into
kaasops:mainfrom
gecube:fix/issue-232-hash-int32-overflow
Jul 3, 2026
Merged

fix: store config/pipeline hashes as int64 to fit the uint32 range (#232)#233
aa1ex merged 1 commit into
kaasops:mainfrom
gecube:fix/issue-232-hash-int32-overflow

Conversation

@gecube

@gecube gecube commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #232.

ClusterVectorPipeline (and, as it turns out, the Vector/VectorAggregator/ClusterVectorAggregator resources) can get permanently stuck with configCheckResult: false even though the config check succeeds, with the operator log looping on:

status: Invalid value: "": Checked value must be of type integer with format int32 in LastAppliedPipelineHash

Root cause

The config/pipeline hash is a CRC32 checksum — a uint32 in the range 0..4294967295 (internal/utils/hash). It is stored in the status as a Go *uint32, which makes controller-gen emit format: int32 in the CRD schema.

int32 maxes out at 2147483647, so any hash above that ceiling — roughly half of all values — is rejected by the API server on the status update. The update fails on every reconcile, the resource never reaches VALID: true, and the reconcile loop retries forever. The Invalid value: "" wording is just how the apiserver's int32 range validator reports an out-of-range integer.

This is not specific to ClusterVectorPipeline — the namespaced VectorPipeline only appeared unaffected because its hash happened to fall below the int32 ceiling. The same defect exists in VectorCommonStatus.LastAppliedConfigHash / LastAppliedGlobalConfigHash, which back the Vector agent and aggregator CRDs.

Reproduction

On a kind cluster (k8s v1.36), with the unpatched CRD:

# hash below int32 max — accepted
kubectl patch clustervectorpipeline x --subresource=status --type=merge \
  -p '{"status":{"LastAppliedPipelineHash":12345}}'          # patched

# crc32("test") = 3632233996, above int32 max — rejected
kubectl patch clustervectorpipeline x --subresource=status --type=merge \
  -p '{"status":{"LastAppliedPipelineHash":3632233996}}'
# The ClusterVectorPipeline "x" is invalid: status: Invalid value: "":
# Checked value must be of type integer with format int32 in LastAppliedPipelineHash

Fix

Store the hashes as int64, which fully contains the uint32 range:

  • VectorPipelineStatus.LastAppliedPipelineHash
  • VectorCommonStatus.LastAppliedConfigHash
  • VectorCommonStatus.LastAppliedGlobalConfigHash

GetPipelineHash / GetGlobalConfigHash and the controllers now widen the uint32 CRC32 to int64 (int64(hash.Get(...))), so the value is always non-negative and never overflows. int64 is backward compatible with the int32-range values already persisted in existing resources' status.

CRDs regenerated with controller-gen v0.16.1; the helm-chart CRD copies under helm/charts/vector-operator/crds were synced to match.

Testing

  • go build ./..., go vet, gofmt clean.
  • go test ./internal/pipeline/... ./internal/utils/hash/... pass, including a new regression test (TestLastAppliedPipelineHashHoldsFullUint32Range) asserting a uint32 above the int32 ceiling round-trips through the status field without overflow.
  • Verified end-to-end on kind with the regenerated CRD: the status schema is now format: int64, and status updates with 3632233996 and 4294967295 (max uint32) are accepted, with configCheckResult: true persisting.

The pipeline and Vector config hashes are CRC32 checksums (uint32,
0..4294967295), but their status fields were int32 (*uint32 in Go makes
controller-gen emit format: int32). Any hash above the int32 ceiling
(2147483647) - roughly half of all values - is rejected by the API server:

    status: Invalid value: "": Checked value must be of type integer
    with format int32 in LastAppliedPipelineHash

The status update then fails on every reconcile, so the resource stays
stuck with configCheckResult=false and the reconcile loop retries forever.
VectorPipeline only appeared unaffected when its hash happened to land
below the int32 ceiling; the defect is not specific to ClusterVectorPipeline.

Store the hashes as int64, which fully contains the uint32 range:
  - VectorPipelineStatus.LastAppliedPipelineHash
  - VectorCommonStatus.LastAppliedConfigHash
  - VectorCommonStatus.LastAppliedGlobalConfigHash

int64 is backward compatible with the int32-range values already persisted
in status. CRDs regenerated with controller-gen v0.16.1 and the helm chart
CRD copies synced.

Fixes kaasops#232

Signed-off-by: Gaál György <gb12335@gmail.com>

@aa1ex aa1ex left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Nice catch, on 1.36+ this really does fire (kubernetes/kubernetes#136582). LGTM.

@aa1ex
aa1ex merged commit 809e9fc into kaasops:main Jul 3, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ClusterVectorPipeline stuck VALID: false — operator writes "" instead of int32 to LastAppliedPipelineHash after successful config check

2 participants