rialo_feature_management_interface/error.rs
1// Copyright (c) Subzero Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Error types for the Feature Management Program
5
6use rialo_s_instruction::error::InstructionError;
7use rialo_s_program_error::{PrintProgramError, ProgramError};
8
9/// Errors that can be returned by the Feature Management Program
10///
11/// **Stable from this commit forward.** Discriminants surface as
12/// `ProgramError::Custom(u32)` over the wire, so reordering or renumbering
13/// silently shifts what external decoders see. Pre-launch this enum has
14/// been compacted to fill the gaps left by the dropped sticky/windowed
15/// variants; from now on, add new variants only at the tail with the next
16/// unused discriminant.
17#[derive(Debug, Clone, PartialEq, Eq)]
18#[repr(u32)]
19pub enum FeatureManagementError {
20 /// Unauthorized access - signature verification failed
21 Unauthorized = 0,
22
23 /// Invalid feature name (empty or too long)
24 InvalidFeatureName = 1,
25
26 /// Feature not found
27 FeatureNotFound = 2,
28
29 /// Serialization error
30 SerializationError = 3,
31
32 /// Deserialization error
33 DeserializationError = 4,
34
35 /// Invalid instruction data
36 InvalidInstructionData = 5,
37
38 /// Internal error (e.g., mutex lock failure)
39 InternalError = 6,
40
41 /// Duplicate feature in modification list
42 DuplicateFeature = 7,
43
44 /// Invalid storage account (not the expected PDA)
45 InvalidStorageAccount = 8,
46
47 /// Storage account already initialized
48 AlreadyInitialized = 9,
49
50 /// Storage account not initialized
51 NotInitialized = 10,
52
53 /// Maximum feature count exceeded.
54 MaxFeatureCountExceeded = 11,
55
56 /// A single `Enable` instruction submitted more names than
57 /// `MAX_NAMES_PER_BATCH` permits.
58 TooManyNames = 12,
59
60 /// `AcceptAuthorityTransfer` / `CancelAuthorityTransfer` invoked while
61 /// no transfer is pending.
62 NoPendingTransfer = 13,
63
64 /// `ProposeAuthorityTransfer` invoked while a previous proposal is
65 /// still outstanding. Cancel the existing proposal first.
66 PendingTransferExists = 14,
67
68 /// `ProposeAuthorityTransfer` invoked with `new_authority` equal to the
69 /// current authority. Distinct from `Unauthorized` — the signer IS the
70 /// authority; the *target* of the transfer is degenerate.
71 InvalidTransferTarget = 15,
72
73 /// `ScheduleEnable` invoked with a `fire_at_ms` at or before the current
74 /// block time. A schedule must activate in the future; use `Enable` for
75 /// immediate activation.
76 ScheduleInPast = 16,
77
78 /// `ScheduleEnable` invoked with a `fire_at_ms` more than
79 /// `MAX_SCHEDULE_HORIZON_MS` past the current block time. Guards against
80 /// fat-fingered far-future timestamps (e.g. seconds mistaken for millis).
81 ScheduleTooFarOut = 17,
82
83 /// `Cancel` invoked with a `request_id` that has no pending entry —
84 /// already fired, already cancelled, or never existed.
85 RequestNotFound = 18,
86
87 /// `ScheduleEnable` invoked while the pending set is already at
88 /// `MAX_PENDING_REQUESTS`. Cancel or let existing schedules fire first.
89 TooManyPendingRequests = 19,
90
91 /// `ScheduleEnable` invoked with a `request_id` that already has a pending
92 /// entry.
93 RequestAlreadyExists = 20,
94
95 /// `ScheduleEnable` whose new pending entry would push the serialized
96 /// `FeaturesState` over `MAX_FEATURES_STATE_SIZE`. The byte budget — not
97 /// `MAX_PENDING_REQUESTS` — is the binding cap once requests carry
98 /// non-trivial batches, so this is surfaced explicitly rather than as a
99 /// bare `SerializationError` at save time.
100 PendingStateTooLarge = 21,
101}
102
103impl From<FeatureManagementError> for ProgramError {
104 fn from(e: FeatureManagementError) -> Self {
105 ProgramError::Custom(e as u32)
106 }
107}
108
109impl From<FeatureManagementError> for InstructionError {
110 fn from(e: FeatureManagementError) -> Self {
111 InstructionError::Custom(e as u32)
112 }
113}
114
115impl PrintProgramError for FeatureManagementError {
116 fn print<E>(&self) {}
117}