usememos/memos · error

GENERAL instance setting is required

Error message

GENERAL instance setting is required

What it means

UpsertInstanceGeneralSettingSafely requires a fully-formed GENERAL instance setting: a non-nil storepb.InstanceSetting whose Key equals InstanceSettingKey_GENERAL and whose general_setting oneof is populated. Any nil argument, wrong key, or missing oneof content yields this error before marshaling or transactional validation begins.

Source

Thrown at store/auth_config.go:34

var ErrUnsafeAuthenticationConfiguration = errors.New("password authentication for regular users cannot be disabled without an effective identity provider")

// AuthenticationConfigState is the stored authentication configuration read inside a transaction.
type AuthenticationConfigState struct {
	GeneralSetting    *InstanceSetting
	IdentityProviders []*IdentityProvider
}

// AuthenticationConfigMutation validates and applies one stored authentication mutation atomically.
type AuthenticationConfigMutation struct {
	UpsertGeneralSetting     *InstanceSetting
	DeleteIdentityProviderID *int32
	Validate                 func(*AuthenticationConfigState) error
}

// UpsertInstanceGeneralSettingSafely validates and stores GENERAL as one serialized operation.
func (s *Store) UpsertInstanceGeneralSettingSafely(ctx context.Context, setting *storepb.InstanceSetting) (*storepb.InstanceSetting, error) {
	if setting == nil || setting.Key != storepb.InstanceSettingKey_GENERAL || setting.GetGeneralSetting() == nil {
		return nil, errors.New("GENERAL instance setting is required")
	}
	value, err := protojson.Marshal(setting.GetGeneralSetting())
	if err != nil {
		return nil, errors.Wrap(err, "failed to marshal GENERAL instance setting")
	}
	raw := &InstanceSetting{Name: storepb.InstanceSettingKey_GENERAL.String(), Value: string(value)}
	mutation := &AuthenticationConfigMutation{
		UpsertGeneralSetting: raw,
		Validate: func(state *AuthenticationConfigState) error {
			return s.validateAuthenticationMutationState(state, setting.GetGeneralSetting(), nil)
		},
	}
	if err := s.applyAuthenticationConfigMutation(ctx, mutation); err != nil {
		return nil, err
	}
	result := cloneInstanceSetting(setting)
	s.cacheInstanceSetting(ctx, result)
	return result, nil

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Construct the full message: Key: storepb.InstanceSettingKey_GENERAL and GeneralSetting: &storepb.InstanceSetting_GeneralSetting{...}
  2. Nil-check the parsed message's GetGeneralSetting() before upserting
  3. Log the setting key and oneof presence when this validation fails to catch construction bugs

Example fix

// before
_, err := s.UpsertInstanceGeneralSettingSafely(ctx, &storepb.InstanceSetting{})
// after
_, err := s.UpsertInstanceGeneralSettingSafely(ctx, &storepb.InstanceSetting{
    Key: storepb.InstanceSettingKey_GENERAL,
    Value: &storepb.InstanceSetting_GeneralSetting{
        GeneralSetting: general,
    },
})
Defensive patterns

Strategy: type-guard

Validate before calling

if setting == nil || setting.Key != storepb.InstanceSettingKey_GENERAL || setting.GetGeneralSetting() == nil {
    return errors.New("refusing to upsert malformed GENERAL setting")
}

Type guard

func isGeneralSetting(s *storepb.InstanceSetting) bool {
    return s != nil &&
        s.Key == storepb.InstanceSettingKey_GENERAL &&
        s.GetGeneralSetting() != nil
}

Prevention

When it happens

Trigger: Passing nil; passing a setting with Key set to another InstanceSettingKey; passing a GENERAL-keyed setting whose GetGeneralSetting() is nil.

Common situations: Callers building InstanceSetting piecemeal and forgetting the oneof; deserializing a setting from JSON where the general_setting field was absent; copy-paste from another setting's upsert path.

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/dc9825575c6c6e09. Report an issue: GitHub.