OtterMind/Chat2DB · error · BusinessException

ai.model.config.required

ai.model.config.required

Error message

ai.model.config.required

What it means

Thrown by AiModelConfigServiceImpl.resolveRuntimeModel when request.getModelConfigId() (trimmed) starts with the PRESET_VALUE_PREFIX 'preset:'. In Community mode a preset-only id is not a runnable configuration - there is no Gateway/cloud preset resolution - so the service refuses and requires a saved local config. The i18n message resolves to 'Community AI requires a local model configuration. Please save a model configuration first.'

Source

Thrown at chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ai/AiModelConfigServiceImpl.java:238

        if (provider == AiProviderEnum.MINIMAX) {
            String baseUrl = trimToNull(request.getBaseUrl());
            if (StringUtils.isNotBlank(baseUrl) && StringUtils.containsIgnoreCase(baseUrl, "/anthropic")) {
                return testAnthropicCompatibleConfig(request);
            }
            return testOpenAiCompatibleConfig(request, DEFAULT_MINIMAX_BASE_URL);
        }
        return ModelConfigTestResponse.failure(null, null,
                "Connection test currently supports OpenAI-compatible models only.");
    }

    public synchronized AiRuntimeModel resolveRuntimeModel(AiChatRuntimeResolveRequest request) {
        Long userId = identityService.currentUserId();
        AiModelConfig baseConfig = null;
        boolean systemPreset = false;
        if (StringUtils.isNotBlank(request.getModelConfigId())) {
            String modelConfigId = request.getModelConfigId().trim();
            if (modelConfigId.startsWith(PRESET_VALUE_PREFIX)) {
                throw new BusinessException(ERROR_MODEL_CONFIG_REQUIRED);
            } else {
                String resolvedId = modelConfigId.startsWith(CONFIG_VALUE_PREFIX)
                        ? modelConfigId.substring(CONFIG_VALUE_PREFIX.length())
                        : modelConfigId;
                baseConfig = findById(userConfigMap.getOrDefault(userId, new ArrayList<>()), resolvedId);
                if (Objects.isNull(baseConfig)) {
                    throw new BusinessException("ai.model.config.notFound");
                }
            }
        } else if (StringUtils.isNotBlank(request.getProvider()) && StringUtils.isNotBlank(request.getModel())) {
            baseConfig = new AiModelConfig();
            baseConfig.setProvider(request.getProvider());
            baseConfig.setModel(request.getModel());
            baseConfig.setApiKey(request.getApiKey());
            baseConfig.setBaseUrl(request.getBaseUrl());
            baseConfig.setProjectId(request.getProjectId());
            baseConfig.setLocation(request.getLocation());
            baseConfig.setTemperature(request.getTemperature());

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Save a real model configuration (provider, model, apiKey/baseUrl) via the config endpoint first and send its 'config:<id>' (or bare id) instead of a 'preset:' value.
  2. If the user only has provider+model, send those fields (no modelConfigId) so resolveRuntimeModel builds an ad-hoc config - but note preset provider+model without credentials also fails (see error 54).
  3. Frontend: hide/disable preset-only options in Community edition and never submit 'preset:' ids.

Example fix

// before
resolve.setModelConfigId("preset:openai-gpt-4");

// after
// 1. save a local config
AiModelConfig saved = configService.save(myConfig); // returns id=42
// 2. reference it
resolve.setModelConfigId("config:42");
Defensive patterns

Strategy: validation

Validate before calling

String id = request.getModelConfigId();
if (id != null && id.trim().startsWith("preset:")) {
    return ResponseEntity.badRequest()
        .body("Community requires a saved local model config, not a preset");
}

Try / catch

try {
    service.resolveRuntimeModel(request);
} catch (BusinessException e) {
    if ("ai.model.config.required".equals(e.getCode())) {
        return ResponseEntity.status(428) // precondition required
            .body("save a model configuration first");
    }
    throw e;
}

Prevention

When it happens

Trigger: The frontend sends modelConfigId = 'preset:<something>' to resolveRuntimeModel. This happens when the UI lets a user pick a system-preset model directly without saving a local config, which Community does not support.

Common situations: A Community build reusing UI/flows that submit preset ids; a user selected a built-in preset model from a dropdown; the request was constructed from stale cached state holding a preset value.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/5d3569f4fbe7e1d8. Report an issue: GitHub.