openAI compatible add-on faild to add LLM #860

Closed
opened 2026-02-16 10:20:45 -05:00 by yindo · 11 comments
Owner

Originally created by @bionexit on GitHub (Dec 8, 2025).

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

1.10.1-fix1

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce


plugin_daemon-1 |[GIN] 2025/12/08 - 08:41:21 | 200 | 10.005556097s |       10.4.2.61 | POST     "/plugin/fd4c7413-2d61-49da-9ef4-168b0faa8710/dispatch/model/validate_model_credentials"
api-1           |2025-12-08 08:41:21.847 INFO [Dummy-731] [_client.py:1038] - HTTP Request: POST http://plugin_daemon:5002/plugin/fd4c7413-2d61-49da-9ef4-168b0faa8710/dispatch/model/validate_model_credentials "HTTP/1.1 200 OK"
api-1           |2025-12-08 08:41:21.849 ERROR [Dummy-731] [base.py:277] - Error in stream response for plugin {'code': -500, 'message': '{"message":"{\\"args\\":{},\\"error_type\\":\\"UnboundLocalError\\",\\"message\\":\\"cannot access local variable \'response\' where it is not associated with a value\\"}","error_type":"PluginInvokeError","args":null}', 'data': None}
nginx-1         |10.0.0.254 - - [08/Dec/2025:08:41:21 +0000] "POST /console/api/workspaces/current/model-providers/langgenius/openai_api_compatible/openai_api_compatible/models/credentials HTTP/1.1" 400 235 "http://10.5.0.1/plugins?action=showSettings&tab=provider" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0" "-"

Tried several editions, all failed to connect LLM

✔️ Expected Behavior

new install dify 1.10.1-fix1 with nerdctl compose [similar as docker compose]

install OpenAI-API-compatible 0.0.26

input elements of OAC add-one and submit

error shows

Image

Actual Behavior

No response

Originally created by @bionexit on GitHub (Dec 8, 2025). ### Self Checks - [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). - [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [x] I confirm that I am using English to submit this report, otherwise it will be closed. - [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) - [x] Please do not modify this template :) and fill in all the required fields. ### Dify version 1.10.1-fix1 ### Cloud or Self Hosted Self Hosted (Docker) ### Steps to reproduce ``` plugin_daemon-1 |[GIN] 2025/12/08 - 08:41:21 | 200 | 10.005556097s | 10.4.2.61 | POST "/plugin/fd4c7413-2d61-49da-9ef4-168b0faa8710/dispatch/model/validate_model_credentials" api-1 |2025-12-08 08:41:21.847 INFO [Dummy-731] [_client.py:1038] - HTTP Request: POST http://plugin_daemon:5002/plugin/fd4c7413-2d61-49da-9ef4-168b0faa8710/dispatch/model/validate_model_credentials "HTTP/1.1 200 OK" api-1 |2025-12-08 08:41:21.849 ERROR [Dummy-731] [base.py:277] - Error in stream response for plugin {'code': -500, 'message': '{"message":"{\\"args\\":{},\\"error_type\\":\\"UnboundLocalError\\",\\"message\\":\\"cannot access local variable \'response\' where it is not associated with a value\\"}","error_type":"PluginInvokeError","args":null}', 'data': None} nginx-1 |10.0.0.254 - - [08/Dec/2025:08:41:21 +0000] "POST /console/api/workspaces/current/model-providers/langgenius/openai_api_compatible/openai_api_compatible/models/credentials HTTP/1.1" 400 235 "http://10.5.0.1/plugins?action=showSettings&tab=provider" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0" "-" ``` Tried several editions, all failed to connect LLM ### ✔️ Expected Behavior new install dify 1.10.1-fix1 with nerdctl compose [similar as docker compose] install OpenAI-API-compatible 0.0.26 input elements of OAC add-one and submit error shows <img width="392" height="165" alt="Image" src="https://github.com/user-attachments/assets/8799f2ac-a836-4977-b8e5-b00d170eee0c" /> ### ❌ Actual Behavior _No response_
yindo added the bug label 2026-02-16 10:20:45 -05:00
yindo closed this issue 2026-02-16 10:20:45 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Dec 8, 2025):

This is a known bug in recent Dify versions: the UnboundLocalError happens because the plugin credential validation code tries to access the response variable before it's assigned, especially when credentials (like API keys) are missing or empty. This breaks the add-on flow for OpenAI-compatible LLMs and similar plugins in self-hosted Docker setups [details & workaround].

Workaround:
Patch the backend to skip credential validation if credentials are empty. In your Dify install, edit api/core/plugin/impl/model.py and update the validate_model_credentials method like this:

def validate_model_credentials(
    self,
    tenant_id: str,
    user_id: str,
    plugin_id: str,
    provider: str,
    model_type: str,
    model: str,
    credentials: dict,
) -> bool:
    # Workaround: skip validation if credentials are empty
    if not credentials or all(not v for v in credentials.values()):
        return True

    response = self._request_with_plugin_daemon_response_stream(
        "POST",
        f"plugin/{tenant_id}/dispatch/model/validate_model_credentials",
        PluginBasicBooleanResponse,
        data={
            "user_id": user_id,
            "data": {
                "provider": provider,
                "model_type": model_type,
                "model": model,
                "credentials": credentials,
            },
        },
        headers={
            "X-Plugin-ID": plugin_id,
            "Content-Type": "application/json",
        },
    )

    for resp in response:
        if resp.credentials and isinstance(resp.credentials, dict):
            credentials.update(resp.credentials)
        return resp.result

    return False

After saving, restart your API container. This is safe for self-hosted setups and only affects models with empty credentials [source].

Other things to check:

  • Make sure your Docker network config is correct: use host.docker.internal or your host's LAN IP for endpoints, not localhost or 127.0.0.1 [network tips].
  • If you use HTTPS with self-signed certs, you may need to disable certificate verification in the plugin's HTTP requests or import your LLM server's cert into the plugin-daemon container [cert workaround].

If you can't patch the code, some users have worked around this by downgrading to Dify 0.15.3, which has more permissive credential validation logic [reference].

Let me know if you need step-by-step instructions for any of these changes.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Dec 8, 2025): <!-- Answer --> This is a known bug in recent Dify versions: the UnboundLocalError happens because the plugin credential validation code tries to access the response variable before it's assigned, especially when credentials (like API keys) are missing or empty. This breaks the add-on flow for OpenAI-compatible LLMs and similar plugins in self-hosted Docker setups [[details & workaround](https://github.com/langgenius/dify/issues/27789)]. **Workaround:** Patch the backend to skip credential validation if credentials are empty. In your Dify install, edit `api/core/plugin/impl/model.py` and update the `validate_model_credentials` method like this: ```python def validate_model_credentials( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model_type: str, model: str, credentials: dict, ) -> bool: # Workaround: skip validation if credentials are empty if not credentials or all(not v for v in credentials.values()): return True response = self._request_with_plugin_daemon_response_stream( "POST", f"plugin/{tenant_id}/dispatch/model/validate_model_credentials", PluginBasicBooleanResponse, data={ "user_id": user_id, "data": { "provider": provider, "model_type": model_type, "model": model, "credentials": credentials, }, }, headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: if resp.credentials and isinstance(resp.credentials, dict): credentials.update(resp.credentials) return resp.result return False ``` After saving, restart your API container. This is safe for self-hosted setups and only affects models with empty credentials [[source](https://github.com/langgenius/dify/issues/27789)]. **Other things to check:** - Make sure your Docker network config is correct: use `host.docker.internal` or your host's LAN IP for endpoints, not `localhost` or `127.0.0.1` [[network tips](https://github.com/langgenius/dify-docs/issues/543)]. - If you use HTTPS with self-signed certs, you may need to disable certificate verification in the plugin's HTTP requests or import your LLM server's cert into the plugin-daemon container [[cert workaround](https://github.com/langgenius/dify/issues/27789)]. If you can't patch the code, some users have worked around this by downgrading to Dify 0.15.3, which has more permissive credential validation logic [[reference](https://github.com/langgenius/dify-official-plugins/issues/1542)]. Let me know if you need step-by-step instructions for any of these changes. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/8bdb8d22-d492-4222-ad7b-684f7da037f1?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/8bdb8d22-d492-4222-ad7b-684f7da037f1?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/8bdb8d22-d492-4222-ad7b-684f7da037f1?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/8bdb8d22-d492-4222-ad7b-684f7da037f1?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/8bdb8d22-d492-4222-ad7b-684f7da037f1?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/8bdb8d22-d492-4222-ad7b-684f7da037f1?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/8bdb8d22-d492-4222-ad7b-684f7da037f1?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20is%20a%20known%20bug%20in%20recent%20Dify%20versions%3A%20the%20UnboundLocalError%20happens%20because%20the%20plugin%20credential%20validation%20code%20tries%20to%20access%20the%20response%20variable%20before%20it%27s%20assigned%2C%20especially%20when%20credentials%20%28like%20API%20keys%29%20are%20missing%20or%20empty.%20This%20breaks%20the%20add-on%20flow%20for%20OpenAI-compatible%20LLMs%20and%20similar%20plugins%20in%20self-hosted%20Docker%20setups%20%5B%5Bdetails%20%26%20workaround%5D%28https%3A//github.com/langgenius/dify/issues/27789%29%5D.%0A%0A%2A%2AWorkaround%3A%2A%2A%20%20%0APatch%20the%20backend%20to%20skip%20credential%20validation%20if%20credentials%20are%20empty.%20In%20your%20Dify%20install%2C%20edit%20%60api/core/plugin/impl/model.py%60%20and%20update%20the%20%60validate_model_credentials%60%20method%20like%20this%3A%0A%0A%60%60%60python%0Adef%20validate_model_credentials%28%0A%20%20%20%20self%2C%0A%20%20%20%20tenant_id%3A%20str%2C%0A%20%20%20%20user_id%3A%20str%2C%0A%20%20%20%20plugin_id%3A%20str%2C%0A%20%20%20%20provider%3A%20str%2C%0A%20%20%20%20model_type%3A%20str%2C%0A%20%20%20%20model%3A%20str%2C%0A%20%20%20%20credentials%3A%20dict%2C%0A%29%20-%3E%20bool%3A%0A%20%20%20%20%23%20Workaround%3A%20skip%20validation%20if%20credentials%20are%20empty%0A%20%20%20%20if%20not%20credentials%20or%20all%28not%20v%20for%20v%20in%20credentials.values%28%29%29%3A%0A%20%20%20%20%20%20%20%20return%20True%0A%0A%20%20%20%20response%20%3D%20self._request_with_plugin_daemon_response_stream%28%0A%20%20%20%20%20%20%20%20%22POST%22%2C%0A%20%20%20%20%20%20%20%20f%22plugin/%7Btenant_id%7D/dispatch/model/validate_model_credentials%22%2C%0A%20%20%20%20%20%20%20%20PluginBasicBooleanResponse%2C%0A%20%20%20%20%20%20%20%20data%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22user_id%22%3A%20user_id%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22data%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22provider%22%3A%20provider%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22model_type%22%3A%20model_type%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22model%22%3A%20model%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22credentials%22%3A%20credentials%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20headers%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22X-Plugin-ID%22%3A%20plugin_id%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Content-Type%22%3A%20%22application/json%22%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%29%0A%0A%20%20%20%20for%20resp%20in%20response%3A%0A%20%20%20%20%20%20%20%20if%20resp.credentials%20and%20isinstance%28resp.credentials%2C%20dict%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20credentials.update%28resp.credentials%29%0A%20%20%20%20%20%20%20%20return%20resp.result%0A%0A%20%20%20%20return%20False%0A%60%60%60%0A%0AAfter%20saving%2C%20restart%20your%20API%20container.%20This%20is%20safe%20for%20self-hosted%20setups%20and%20only%20affects%20models%20with%20empty%20credentials%20%5B%5Bsource%5D%28https%3A//github.com/langgenius/dify/issues/27789%29%5D.%0A%0A%2A%2AOther%20things%20to%20check%3A%2A%2A%20%20%0A-%20Make%20sure%20your%20Docker%20network%20config%20is%20correct%3A%20use%20%60host.docker.internal%60%20or%20your%20host%27s%20LAN%20IP%20for%20endpoints%2C%20not%20%60localhost%60%20or%20%60127.0.0.1%60%20%5B%5Bnetwork%20tips%5D%28https%3A//github.com/langgenius/dify-docs/issues/543%29%5D.%0A-%20If%20you%20use%20HTTPS%20with%20self-signed%20certs%2C%20you%20may%20need%20to%20disable%20certificate%20verification%20in%20the%20plugin%27s%20HTTP%20requests%20or%20import%20your%20LLM%20server%27s%20cert%20into%20the%20plugin-daemon%20container%20%5B%5Bcert%20workaround%5D%28https%3A//github.com/langgenius/dify/issues/27789%29%5D.%0A%0AIf%20you%20can%27t%20patch%20the%20code%2C%20some%20users%20have%20worked%20around%20this%20by%20downgrading%20to%20Dify%200.15.3%2C%20which%20has%20more%20permissive%20credential%20validation%20logic%20%5B%5Breference%5D%28https%3A//github.com/langgenius/dify-official-plugins/issues/1542%29%5D.%0A%0ALet%20me%20know%20if%20you%20need%20step-by-step%20instructions%20for%20any%20of%20these%20changes.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/29279)
Author
Owner

@dosubot[bot] commented on GitHub (Dec 8, 2025):

This is a known bug in the OpenAI-compatible add-on for Dify when running self-hosted via Docker. The UnboundLocalError happens because the plugin's credential validation code tries to use the response variable before it's assigned, especially if credentials are missing or empty. This breaks the add-on flow and prevents adding LLMs.

Workaround:
Patch the backend code in api/core/plugin/impl/model.py in the validate_model_credentials method. Add this check at the top of the method:

if not credentials or all(not v for v in credentials.values()):
    return True

This skips validation if credentials are empty and avoids the error. After making this change, restart your API container to apply the fix. This workaround is safe for self-hosted setups and only affects models with empty credentials.
Reference

If you can't patch the code, some users have worked around this by downgrading to Dify 0.15.3, which has more permissive credential validation logic, but this is not ideal for most setups.

Other things to check:

  • Make sure your Docker network config is correct: use host.docker.internal or your host's LAN IP for endpoints, not localhost or 127.0.0.1.
  • If you use HTTPS with self-signed certs, you may need to disable certificate verification in the plugin's HTTP requests or import your LLM server's cert into the plugin-daemon container.

An official fix may be pending in future releases. If you have constraints (like not being able to patch code), let me know so I can suggest alternatives.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Dec 8, 2025): <!-- Answer --> This is a known bug in the OpenAI-compatible add-on for Dify when running self-hosted via Docker. The UnboundLocalError happens because the plugin's credential validation code tries to use the `response` variable before it's assigned, especially if credentials are missing or empty. This breaks the add-on flow and prevents adding LLMs. **Workaround:** Patch the backend code in `api/core/plugin/impl/model.py` in the `validate_model_credentials` method. Add this check at the top of the method: ```python if not credentials or all(not v for v in credentials.values()): return True ``` This skips validation if credentials are empty and avoids the error. After making this change, restart your API container to apply the fix. This workaround is safe for self-hosted setups and only affects models with empty credentials. [Reference](https://github.com/langgenius/dify/issues/29279) If you can't patch the code, some users have worked around this by downgrading to Dify 0.15.3, which has more permissive credential validation logic, but this is not ideal for most setups. Other things to check: - Make sure your Docker network config is correct: use `host.docker.internal` or your host's LAN IP for endpoints, not `localhost` or `127.0.0.1`. - If you use HTTPS with self-signed certs, you may need to disable certificate verification in the plugin's HTTP requests or import your LLM server's cert into the plugin-daemon container. An official fix may be pending in future releases. If you have constraints (like not being able to patch code), let me know so I can suggest alternatives. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/ceefa29a-496b-413c-a668-b3aeb6f2a4d7?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/ceefa29a-496b-413c-a668-b3aeb6f2a4d7?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/ceefa29a-496b-413c-a668-b3aeb6f2a4d7?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/ceefa29a-496b-413c-a668-b3aeb6f2a4d7?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/ceefa29a-496b-413c-a668-b3aeb6f2a4d7?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/ceefa29a-496b-413c-a668-b3aeb6f2a4d7?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/ceefa29a-496b-413c-a668-b3aeb6f2a4d7?feedback_type=other)</sup> [![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20is%20a%20known%20bug%20in%20the%20OpenAI-compatible%20add-on%20for%20Dify%20when%20running%20self-hosted%20via%20Docker.%20The%20UnboundLocalError%20happens%20because%20the%20plugin%27s%20credential%20validation%20code%20tries%20to%20use%20the%20%60response%60%20variable%20before%20it%27s%20assigned%2C%20especially%20if%20credentials%20are%20missing%20or%20empty.%20This%20breaks%20the%20add-on%20flow%20and%20prevents%20adding%20LLMs.%0A%0A%2A%2AWorkaround%3A%2A%2A%20%20%0APatch%20the%20backend%20code%20in%20%60api/core/plugin/impl/model.py%60%20in%20the%20%60validate_model_credentials%60%20method.%20Add%20this%20check%20at%20the%20top%20of%20the%20method%3A%0A%0A%60%60%60python%0Aif%20not%20credentials%20or%20all%28not%20v%20for%20v%20in%20credentials.values%28%29%29%3A%0A%20%20%20%20return%20True%0A%60%60%60%0A%0AThis%20skips%20validation%20if%20credentials%20are%20empty%20and%20avoids%20the%20error.%20After%20making%20this%20change%2C%20restart%20your%20API%20container%20to%20apply%20the%20fix.%20This%20workaround%20is%20safe%20for%20self-hosted%20setups%20and%20only%20affects%20models%20with%20empty%20credentials.%20%20%0A%5BReference%5D%28https%3A//github.com/langgenius/dify/issues/29279%29%0A%0AIf%20you%20can%27t%20patch%20the%20code%2C%20some%20users%20have%20worked%20around%20this%20by%20downgrading%20to%20Dify%200.15.3%2C%20which%20has%20more%20permissive%20credential%20validation%20logic%2C%20but%20this%20is%20not%20ideal%20for%20most%20setups.%0A%0AOther%20things%20to%20check%3A%20%20%0A-%20Make%20sure%20your%20Docker%20network%20config%20is%20correct%3A%20use%20%60host.docker.internal%60%20or%20your%20host%27s%20LAN%20IP%20for%20endpoints%2C%20not%20%60localhost%60%20or%20%60127.0.0.1%60.%0A-%20If%20you%20use%20HTTPS%20with%20self-signed%20certs%2C%20you%20may%20need%20to%20disable%20certificate%20verification%20in%20the%20plugin%27s%20HTTP%20requests%20or%20import%20your%20LLM%20server%27s%20cert%20into%20the%20plugin-daemon%20container.%0A%0AAn%20official%20fix%20may%20be%20pending%20in%20future%20releases.%20If%20you%20have%20constraints%20%28like%20not%20being%20able%20to%20patch%20code%29%2C%20let%20me%20know%20so%20I%20can%20suggest%20alternatives.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify-official-plugins/issues/2203)
Author
Owner

@bionexit commented on GitHub (Dec 8, 2025):

@dosu
hence i deployed as docker-compose, how i make the modification

@bionexit commented on GitHub (Dec 8, 2025): @dosu hence i deployed as docker-compose, how i make the modification
Author
Owner

@dosubot[bot] commented on GitHub (Dec 8, 2025):

In your docker-compose deployment, the backend code is inside the container image and not directly editable from the host. You have two options to apply the patch:

Option 1: Patch inside the running container (quick, but not persistent)

  1. Open a shell in the running API container:
    docker compose exec api /bin/bash
    
    (or use nerdctl compose exec api /bin/bash if you're using nerdctl)
  2. Find and edit the file:
    vi /app/api/core/plugin/impl/model.py
    
    Add this at the top of the validate_model_credentials method:
    if not credentials or all(not v for v in credentials.values()):
        return True
    
  3. Exit and restart the API container:
    docker compose restart api
    
    (or nerdctl compose restart api)

Note: This change will be lost if you update or recreate the container.


Option 2: Rebuild the image with your patch (persistent)

  1. Clone the Dify repo locally and make your code change in api/core/plugin/impl/model.py.
  2. Build a new image:
    docker build -t my-dify-api:patched ./api
    
  3. Edit your docker-compose.yaml to use my-dify-api:patched for the api service.
  4. Restart the stack:
    docker compose up -d --force-recreate api
    
    (or nerdctl compose up -d --force-recreate api)

After patching, retry adding your LLM and check the logs for errors. If you update Dify in the future, you’ll need to reapply your patch.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Dec 8, 2025): <!-- Answer --> In your docker-compose deployment, the backend code is inside the container image and not directly editable from the host. You have two options to apply the patch: **Option 1: Patch inside the running container (quick, but not persistent)** 1. Open a shell in the running API container: ``` docker compose exec api /bin/bash ``` (or use `nerdctl compose exec api /bin/bash` if you're using nerdctl) 2. Find and edit the file: ``` vi /app/api/core/plugin/impl/model.py ``` Add this at the top of the `validate_model_credentials` method: ```python if not credentials or all(not v for v in credentials.values()): return True ``` 3. Exit and restart the API container: ``` docker compose restart api ``` (or `nerdctl compose restart api`) **Note:** This change will be lost if you update or recreate the container. --- **Option 2: Rebuild the image with your patch (persistent)** 1. Clone the Dify repo locally and make your code change in `api/core/plugin/impl/model.py`. 2. Build a new image: ``` docker build -t my-dify-api:patched ./api ``` 3. Edit your `docker-compose.yaml` to use `my-dify-api:patched` for the `api` service. 4. Restart the stack: ``` docker compose up -d --force-recreate api ``` (or `nerdctl compose up -d --force-recreate api`) --- After patching, retry adding your LLM and check the logs for errors. If you update Dify in the future, you’ll need to reapply your patch. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=other)</sup> [![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=In%20your%20docker-compose%20deployment%2C%20the%20backend%20code%20is%20inside%20the%20container%20image%20and%20not%20directly%20editable%20from%20the%20host.%20You%20have%20two%20options%20to%20apply%20the%20patch%3A%0A%0A%2A%2AOption%201%3A%20Patch%20inside%20the%20running%20container%20%28quick%2C%20but%20not%20persistent%29%2A%2A%0A1.%20Open%20a%20shell%20in%20the%20running%20API%20container%3A%0A%20%20%20%60%60%60%0A%20%20%20docker%20compose%20exec%20api%20/bin/bash%0A%20%20%20%60%60%60%0A%20%20%20%28or%20use%20%60nerdctl%20compose%20exec%20api%20/bin/bash%60%20if%20you%27re%20using%20nerdctl%29%0A2.%20Find%20and%20edit%20the%20file%3A%0A%20%20%20%60%60%60%0A%20%20%20vi%20/app/api/core/plugin/impl/model.py%0A%20%20%20%60%60%60%0A%20%20%20Add%20this%20at%20the%20top%20of%20the%20%60validate_model_credentials%60%20method%3A%0A%20%20%20%60%60%60python%0A%20%20%20if%20not%20credentials%20or%20all%28not%20v%20for%20v%20in%20credentials.values%28%29%29%3A%0A%20%20%20%20%20%20%20return%20True%0A%20%20%20%60%60%60%0A3.%20Exit%20and%20restart%20the%20API%20container%3A%0A%20%20%20%60%60%60%0A%20%20%20docker%20compose%20restart%20api%0A%20%20%20%60%60%60%0A%20%20%20%28or%20%60nerdctl%20compose%20restart%20api%60%29%0A%0A%2A%2ANote%3A%2A%2A%20This%20change%20will%20be%20lost%20if%20you%20update%20or%20recreate%20the%20container.%0A%0A---%0A%0A%2A%2AOption%202%3A%20Rebuild%20the%20image%20with%20your%20patch%20%28persistent%29%2A%2A%0A1.%20Clone%20the%20Dify%20repo%20locally%20and%20make%20your%20code%20change%20in%20%60api/core/plugin/impl/model.py%60.%0A2.%20Build%20a%20new%20image%3A%0A%20%20%20%60%60%60%0A%20%20%20docker%20build%20-t%20my-dify-api%3Apatched%20./api%0A%20%20%20%60%60%60%0A3.%20Edit%20your%20%60docker-compose.yaml%60%20to%20use%20%60my-dify-api%3Apatched%60%20for%20the%20%60api%60%20service.%0A4.%20Restart%20the%20stack%3A%0A%20%20%20%60%60%60%0A%20%20%20docker%20compose%20up%20-d%20--force-recreate%20api%0A%20%20%20%60%60%60%0A%20%20%20%28or%20%60nerdctl%20compose%20up%20-d%20--force-recreate%20api%60%29%0A%0A---%0A%0AAfter%20patching%2C%20retry%20adding%20your%20LLM%20and%20check%20the%20logs%20for%20errors.%20If%20you%20update%20Dify%20in%20the%20future%2C%20you%E2%80%99ll%20need%20to%20reapply%20your%20patch.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify-official-plugins/issues/2203)
Author
Owner

@bionexit commented on GitHub (Dec 8, 2025):

@dosu

I rebuild the docker image followed your instruction, modified model.py as follwing

dify@worker:/app/api$ cat core/plugin/impl/model.py 
import binascii
from collections.abc import Generator, Sequence
from typing import IO

from core.model_runtime.entities.llm_entities import LLMResultChunk
from core.model_runtime.entities.message_entities import PromptMessage, PromptMessageTool
from core.model_runtime.entities.model_entities import AIModelEntity
from core.model_runtime.entities.rerank_entities import RerankResult
from core.model_runtime.entities.text_embedding_entities import TextEmbeddingResult
from core.model_runtime.utils.encoders import jsonable_encoder
from core.plugin.entities.plugin_daemon import (
    PluginBasicBooleanResponse,
    PluginDaemonInnerError,
    PluginLLMNumTokensResponse,
    PluginModelProviderEntity,
    PluginModelSchemaEntity,
    PluginStringResultResponse,
    PluginTextEmbeddingNumTokensResponse,
    PluginVoicesResponse,
)
from core.plugin.impl.base import BasePluginClient


class PluginModelClient(BasePluginClient):
    def fetch_model_providers(self, tenant_id: str) -> Sequence[PluginModelProviderEntity]:
        """
        Fetch model providers for the given tenant.
        """
        response = self._request_with_plugin_daemon_response(
            "GET",
            f"plugin/{tenant_id}/management/models",
            list[PluginModelProviderEntity],
            params={"page": 1, "page_size": 256},
        )
        return response

    def get_model_schema(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model_type: str,
        model: str,
        credentials: dict,
    ) -> AIModelEntity | None:
        """
        Get model schema
        """
        response = self._request_with_plugin_daemon_response_stream(
            "POST",
            f"plugin/{tenant_id}/dispatch/model/schema",
            PluginModelSchemaEntity,
            data={
                "user_id": user_id,
                "data": {
                    "provider": provider,
                    "model_type": model_type,
                    "model": model,
                    "credentials": credentials,
                },
            },
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            return resp.model_schema

        return None

    def validate_provider_credentials(
        self, tenant_id: str, user_id: str, plugin_id: str, provider: str, credentials: dict
    ) -> bool:
        """
        validate the credentials of the provider
        """
        if not credentials or all(not v for v in credentials.values()):
            return True
        response = self._request_with_plugin_daemon_response_stream(
            "POST",
            f"plugin/{tenant_id}/dispatch/model/validate_provider_credentials",
            PluginBasicBooleanResponse,
            data={
                "user_id": user_id,
                "data": {
                    "provider": provider,
                    "credentials": credentials,
                },
            },
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            if resp.credentials and isinstance(resp.credentials, dict):
                credentials.update(resp.credentials)

            return resp.result

        return False

    def validate_model_credentials(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model_type: str,
        model: str,
        credentials: dict,
    ) -> bool:
        """
        validate the credentials of the provider
        """
        response = self._request_with_plugin_daemon_response_stream(
            "POST",
            f"plugin/{tenant_id}/dispatch/model/validate_model_credentials",
            PluginBasicBooleanResponse,
            data={
                "user_id": user_id,
                "data": {
                    "provider": provider,
                    "model_type": model_type,
                    "model": model,
                    "credentials": credentials,
                },
            },
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            if resp.credentials and isinstance(resp.credentials, dict):
                credentials.update(resp.credentials)

            return resp.result

        return False

    def invoke_llm(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model: str,
        credentials: dict,
        prompt_messages: list[PromptMessage],
        model_parameters: dict | None = None,
        tools: list[PromptMessageTool] | None = None,
        stop: list[str] | None = None,
        stream: bool = True,
    ) -> Generator[LLMResultChunk, None, None]:
        """
        Invoke llm
        """
        response = self._request_with_plugin_daemon_response_stream(
            method="POST",
            path=f"plugin/{tenant_id}/dispatch/llm/invoke",
            type_=LLMResultChunk,
            data=jsonable_encoder(
                {
                    "user_id": user_id,
                    "data": {
                        "provider": provider,
                        "model_type": "llm",
                        "model": model,
                        "credentials": credentials,
                        "prompt_messages": prompt_messages,
                        "model_parameters": model_parameters,
                        "tools": tools,
                        "stop": stop,
                        "stream": stream,
                    },
                }
            ),
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        try:
            yield from response
        except PluginDaemonInnerError as e:
            raise ValueError(e.message + str(e.code))

    def get_llm_num_tokens(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model_type: str,
        model: str,
        credentials: dict,
        prompt_messages: list[PromptMessage],
        tools: list[PromptMessageTool] | None = None,
    ) -> int:
        """
        Get number of tokens for llm
        """
        response = self._request_with_plugin_daemon_response_stream(
            method="POST",
            path=f"plugin/{tenant_id}/dispatch/llm/num_tokens",
            type_=PluginLLMNumTokensResponse,
            data=jsonable_encoder(
                {
                    "user_id": user_id,
                    "data": {
                        "provider": provider,
                        "model_type": model_type,
                        "model": model,
                        "credentials": credentials,
                        "prompt_messages": prompt_messages,
                        "tools": tools,
                    },
                }
            ),
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            return resp.num_tokens

        return 0

    def invoke_text_embedding(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model: str,
        credentials: dict,
        texts: list[str],
        input_type: str,
    ) -> TextEmbeddingResult:
        """
        Invoke text embedding
        """
        response = self._request_with_plugin_daemon_response_stream(
            method="POST",
            path=f"plugin/{tenant_id}/dispatch/text_embedding/invoke",
            type_=TextEmbeddingResult,
            data=jsonable_encoder(
                {
                    "user_id": user_id,
                    "data": {
                        "provider": provider,
                        "model_type": "text-embedding",
                        "model": model,
                        "credentials": credentials,
                        "texts": texts,
                        "input_type": input_type,
                    },
                }
            ),
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            return resp

        raise ValueError("Failed to invoke text embedding")

    def get_text_embedding_num_tokens(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model: str,
        credentials: dict,
        texts: list[str],
    ) -> list[int]:
        """
        Get number of tokens for text embedding
        """
        response = self._request_with_plugin_daemon_response_stream(
            method="POST",
            path=f"plugin/{tenant_id}/dispatch/text_embedding/num_tokens",
            type_=PluginTextEmbeddingNumTokensResponse,
            data=jsonable_encoder(
                {
                    "user_id": user_id,
                    "data": {
                        "provider": provider,
                        "model_type": "text-embedding",
                        "model": model,
                        "credentials": credentials,
                        "texts": texts,
                    },
                }
            ),
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            return resp.num_tokens

        return []

    def invoke_rerank(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model: str,
        credentials: dict,
        query: str,
        docs: list[str],
        score_threshold: float | None = None,
        top_n: int | None = None,
    ) -> RerankResult:
        """
        Invoke rerank
        """
        response = self._request_with_plugin_daemon_response_stream(
            method="POST",
            path=f"plugin/{tenant_id}/dispatch/rerank/invoke",
            type_=RerankResult,
            data=jsonable_encoder(
                {
                    "user_id": user_id,
                    "data": {
                        "provider": provider,
                        "model_type": "rerank",
                        "model": model,
                        "credentials": credentials,
                        "query": query,
                        "docs": docs,
                        "score_threshold": score_threshold,
                        "top_n": top_n,
                    },
                }
            ),
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            return resp

        raise ValueError("Failed to invoke rerank")

    def invoke_tts(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model: str,
        credentials: dict,
        content_text: str,
        voice: str,
    ) -> Generator[bytes, None, None]:
        """
        Invoke tts
        """
        response = self._request_with_plugin_daemon_response_stream(
            method="POST",
            path=f"plugin/{tenant_id}/dispatch/tts/invoke",
            type_=PluginStringResultResponse,
            data=jsonable_encoder(
                {
                    "user_id": user_id,
                    "data": {
                        "provider": provider,
                        "model_type": "tts",
                        "model": model,
                        "credentials": credentials,
                        "tenant_id": tenant_id,
                        "content_text": content_text,
                        "voice": voice,
                    },
                }
            ),
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        try:
            for result in response:
                hex_str = result.result
                yield binascii.unhexlify(hex_str)
        except PluginDaemonInnerError as e:
            raise ValueError(e.message + str(e.code))

    def get_tts_model_voices(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model: str,
        credentials: dict,
        language: str | None = None,
    ):
        """
        Get tts model voices
        """
        response = self._request_with_plugin_daemon_response_stream(
            method="POST",
            path=f"plugin/{tenant_id}/dispatch/tts/model/voices",
            type_=PluginVoicesResponse,
            data=jsonable_encoder(
                {
                    "user_id": user_id,
                    "data": {
                        "provider": provider,
                        "model_type": "tts",
                        "model": model,
                        "credentials": credentials,
                        "language": language,
                    },
                }
            ),
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            voices = []
            for voice in resp.voices:
                voices.append({"name": voice.name, "value": voice.value})

            return voices

        return []

    def invoke_speech_to_text(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model: str,
        credentials: dict,
        file: IO[bytes],
    ) -> str:
        """
        Invoke speech to text
        """
        response = self._request_with_plugin_daemon_response_stream(
            method="POST",
            path=f"plugin/{tenant_id}/dispatch/speech2text/invoke",
            type_=PluginStringResultResponse,
            data=jsonable_encoder(
                {
                    "user_id": user_id,
                    "data": {
                        "provider": provider,
                        "model_type": "speech2text",
                        "model": model,
                        "credentials": credentials,
                        "file": binascii.hexlify(file.read()).decode(),
                    },
                }
            ),
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            return resp.result

        raise ValueError("Failed to invoke speech to text")

    def invoke_moderation(
        self,
        tenant_id: str,
        user_id: str,
        plugin_id: str,
        provider: str,
        model: str,
        credentials: dict,
        text: str,
    ) -> bool:
        """
        Invoke moderation
        """
        response = self._request_with_plugin_daemon_response_stream(
            method="POST",
            path=f"plugin/{tenant_id}/dispatch/moderation/invoke",
            type_=PluginBasicBooleanResponse,
            data=jsonable_encoder(
                {
                    "user_id": user_id,
                    "data": {
                        "provider": provider,
                        "model_type": "moderation",
                        "model": model,
                        "credentials": credentials,
                        "text": text,
                    },
                }
            ),
            headers={
                "X-Plugin-ID": plugin_id,
                "Content-Type": "application/json",
            },
        )

        for resp in response:
            return resp.result

        raise ValueError("Failed to invoke moderation")
dify@worker:/app/api$ 

NOT WORKING , STILL IN ERROR

plugin_daemon-1 |[GIN] 2025/12/08 - 11:06:20 | 200 | 10.006154122s |       10.4.2.89 | POST     "/plugin/fd4c7413-2d61-49da-9ef4-168b0faa8710/dispatch/model/validate_model_credentials"
api-1           |2025-12-08 11:06:20.518 INFO [Dummy-47] [_client.py:1038] - HTTP Request: POST http://plugin_daemon:5002/plugin/fd4c7413-2d61-49da-9ef4-168b0faa8710/dispatch/model/validate_model_credentials "HTTP/1.1 200 OK"
api-1           |2025-12-08 11:06:20.520 ERROR [Dummy-47] [base.py:277] - Error in stream response for plugin {'code': -500, 'message': '{"message":"{\\"args\\":{},\\"error_type\\":\\"UnboundLocalError\\",\\"message\\":\\"cannot access local variable \'response\' where it is not associated with a value\\"}","error_type":"PluginInvokeError","args":null}', 'data': None}
nginx-1         |10.0.0.254 - - [08/Dec/2025:11:06:20 +0000] "POST /console/api/workspaces/current/model-providers/langgenius/openai_api_compatible/openai_api_compatible/models/credentials HTTP/1.1" 400 235 "http://10.5.0.1/plugins?category=discover&action=showSettings&tab=provider" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0" "-"
@bionexit commented on GitHub (Dec 8, 2025): @dosu I rebuild the docker image followed your instruction, modified model.py as follwing ``` dify@worker:/app/api$ cat core/plugin/impl/model.py import binascii from collections.abc import Generator, Sequence from typing import IO from core.model_runtime.entities.llm_entities import LLMResultChunk from core.model_runtime.entities.message_entities import PromptMessage, PromptMessageTool from core.model_runtime.entities.model_entities import AIModelEntity from core.model_runtime.entities.rerank_entities import RerankResult from core.model_runtime.entities.text_embedding_entities import TextEmbeddingResult from core.model_runtime.utils.encoders import jsonable_encoder from core.plugin.entities.plugin_daemon import ( PluginBasicBooleanResponse, PluginDaemonInnerError, PluginLLMNumTokensResponse, PluginModelProviderEntity, PluginModelSchemaEntity, PluginStringResultResponse, PluginTextEmbeddingNumTokensResponse, PluginVoicesResponse, ) from core.plugin.impl.base import BasePluginClient class PluginModelClient(BasePluginClient): def fetch_model_providers(self, tenant_id: str) -> Sequence[PluginModelProviderEntity]: """ Fetch model providers for the given tenant. """ response = self._request_with_plugin_daemon_response( "GET", f"plugin/{tenant_id}/management/models", list[PluginModelProviderEntity], params={"page": 1, "page_size": 256}, ) return response def get_model_schema( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model_type: str, model: str, credentials: dict, ) -> AIModelEntity | None: """ Get model schema """ response = self._request_with_plugin_daemon_response_stream( "POST", f"plugin/{tenant_id}/dispatch/model/schema", PluginModelSchemaEntity, data={ "user_id": user_id, "data": { "provider": provider, "model_type": model_type, "model": model, "credentials": credentials, }, }, headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: return resp.model_schema return None def validate_provider_credentials( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, credentials: dict ) -> bool: """ validate the credentials of the provider """ if not credentials or all(not v for v in credentials.values()): return True response = self._request_with_plugin_daemon_response_stream( "POST", f"plugin/{tenant_id}/dispatch/model/validate_provider_credentials", PluginBasicBooleanResponse, data={ "user_id": user_id, "data": { "provider": provider, "credentials": credentials, }, }, headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: if resp.credentials and isinstance(resp.credentials, dict): credentials.update(resp.credentials) return resp.result return False def validate_model_credentials( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model_type: str, model: str, credentials: dict, ) -> bool: """ validate the credentials of the provider """ response = self._request_with_plugin_daemon_response_stream( "POST", f"plugin/{tenant_id}/dispatch/model/validate_model_credentials", PluginBasicBooleanResponse, data={ "user_id": user_id, "data": { "provider": provider, "model_type": model_type, "model": model, "credentials": credentials, }, }, headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: if resp.credentials and isinstance(resp.credentials, dict): credentials.update(resp.credentials) return resp.result return False def invoke_llm( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model: str, credentials: dict, prompt_messages: list[PromptMessage], model_parameters: dict | None = None, tools: list[PromptMessageTool] | None = None, stop: list[str] | None = None, stream: bool = True, ) -> Generator[LLMResultChunk, None, None]: """ Invoke llm """ response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/llm/invoke", type_=LLMResultChunk, data=jsonable_encoder( { "user_id": user_id, "data": { "provider": provider, "model_type": "llm", "model": model, "credentials": credentials, "prompt_messages": prompt_messages, "model_parameters": model_parameters, "tools": tools, "stop": stop, "stream": stream, }, } ), headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) try: yield from response except PluginDaemonInnerError as e: raise ValueError(e.message + str(e.code)) def get_llm_num_tokens( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model_type: str, model: str, credentials: dict, prompt_messages: list[PromptMessage], tools: list[PromptMessageTool] | None = None, ) -> int: """ Get number of tokens for llm """ response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/llm/num_tokens", type_=PluginLLMNumTokensResponse, data=jsonable_encoder( { "user_id": user_id, "data": { "provider": provider, "model_type": model_type, "model": model, "credentials": credentials, "prompt_messages": prompt_messages, "tools": tools, }, } ), headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: return resp.num_tokens return 0 def invoke_text_embedding( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model: str, credentials: dict, texts: list[str], input_type: str, ) -> TextEmbeddingResult: """ Invoke text embedding """ response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/text_embedding/invoke", type_=TextEmbeddingResult, data=jsonable_encoder( { "user_id": user_id, "data": { "provider": provider, "model_type": "text-embedding", "model": model, "credentials": credentials, "texts": texts, "input_type": input_type, }, } ), headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: return resp raise ValueError("Failed to invoke text embedding") def get_text_embedding_num_tokens( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model: str, credentials: dict, texts: list[str], ) -> list[int]: """ Get number of tokens for text embedding """ response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/text_embedding/num_tokens", type_=PluginTextEmbeddingNumTokensResponse, data=jsonable_encoder( { "user_id": user_id, "data": { "provider": provider, "model_type": "text-embedding", "model": model, "credentials": credentials, "texts": texts, }, } ), headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: return resp.num_tokens return [] def invoke_rerank( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model: str, credentials: dict, query: str, docs: list[str], score_threshold: float | None = None, top_n: int | None = None, ) -> RerankResult: """ Invoke rerank """ response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/rerank/invoke", type_=RerankResult, data=jsonable_encoder( { "user_id": user_id, "data": { "provider": provider, "model_type": "rerank", "model": model, "credentials": credentials, "query": query, "docs": docs, "score_threshold": score_threshold, "top_n": top_n, }, } ), headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: return resp raise ValueError("Failed to invoke rerank") def invoke_tts( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model: str, credentials: dict, content_text: str, voice: str, ) -> Generator[bytes, None, None]: """ Invoke tts """ response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/tts/invoke", type_=PluginStringResultResponse, data=jsonable_encoder( { "user_id": user_id, "data": { "provider": provider, "model_type": "tts", "model": model, "credentials": credentials, "tenant_id": tenant_id, "content_text": content_text, "voice": voice, }, } ), headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) try: for result in response: hex_str = result.result yield binascii.unhexlify(hex_str) except PluginDaemonInnerError as e: raise ValueError(e.message + str(e.code)) def get_tts_model_voices( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model: str, credentials: dict, language: str | None = None, ): """ Get tts model voices """ response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/tts/model/voices", type_=PluginVoicesResponse, data=jsonable_encoder( { "user_id": user_id, "data": { "provider": provider, "model_type": "tts", "model": model, "credentials": credentials, "language": language, }, } ), headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: voices = [] for voice in resp.voices: voices.append({"name": voice.name, "value": voice.value}) return voices return [] def invoke_speech_to_text( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model: str, credentials: dict, file: IO[bytes], ) -> str: """ Invoke speech to text """ response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/speech2text/invoke", type_=PluginStringResultResponse, data=jsonable_encoder( { "user_id": user_id, "data": { "provider": provider, "model_type": "speech2text", "model": model, "credentials": credentials, "file": binascii.hexlify(file.read()).decode(), }, } ), headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: return resp.result raise ValueError("Failed to invoke speech to text") def invoke_moderation( self, tenant_id: str, user_id: str, plugin_id: str, provider: str, model: str, credentials: dict, text: str, ) -> bool: """ Invoke moderation """ response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/moderation/invoke", type_=PluginBasicBooleanResponse, data=jsonable_encoder( { "user_id": user_id, "data": { "provider": provider, "model_type": "moderation", "model": model, "credentials": credentials, "text": text, }, } ), headers={ "X-Plugin-ID": plugin_id, "Content-Type": "application/json", }, ) for resp in response: return resp.result raise ValueError("Failed to invoke moderation") dify@worker:/app/api$ ``` NOT WORKING , STILL IN ERROR ``` plugin_daemon-1 |[GIN] 2025/12/08 - 11:06:20 | 200 | 10.006154122s | 10.4.2.89 | POST "/plugin/fd4c7413-2d61-49da-9ef4-168b0faa8710/dispatch/model/validate_model_credentials" api-1 |2025-12-08 11:06:20.518 INFO [Dummy-47] [_client.py:1038] - HTTP Request: POST http://plugin_daemon:5002/plugin/fd4c7413-2d61-49da-9ef4-168b0faa8710/dispatch/model/validate_model_credentials "HTTP/1.1 200 OK" api-1 |2025-12-08 11:06:20.520 ERROR [Dummy-47] [base.py:277] - Error in stream response for plugin {'code': -500, 'message': '{"message":"{\\"args\\":{},\\"error_type\\":\\"UnboundLocalError\\",\\"message\\":\\"cannot access local variable \'response\' where it is not associated with a value\\"}","error_type":"PluginInvokeError","args":null}', 'data': None} nginx-1 |10.0.0.254 - - [08/Dec/2025:11:06:20 +0000] "POST /console/api/workspaces/current/model-providers/langgenius/openai_api_compatible/openai_api_compatible/models/credentials HTTP/1.1" 400 235 "http://10.5.0.1/plugins?category=discover&action=showSettings&tab=provider" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0" "-" ```
Author
Owner

@dosubot[bot] commented on GitHub (Dec 8, 2025):

The error is still happening because the patch was only added to validate_provider_credentials, not to validate_model_credentials—which is the method actually used during the failing OpenAI-compatible add-on flow. To fix this, you need to add the following at the very start of the validate_model_credentials method in core/plugin/impl/model.py:

if not credentials or all(not v for v in credentials.values()):
    return True

This will skip validation if credentials are empty and prevent the UnboundLocalError. After making this change, rebuild your API Docker image and restart the API container. This fix is confirmed by multiple sources and is the recommended workaround for this bug (reference).

If you’re using HTTPS endpoints with self-signed certificates, you may also need to disable certificate verification in the plugin code or import your LLM server’s cert into the plugin-daemon container to avoid related errors.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Dec 8, 2025): <!-- Answer --> The error is still happening because the patch was only added to validate_provider_credentials, not to validate_model_credentials—which is the method actually used during the failing OpenAI-compatible add-on flow. To fix this, you need to add the following at the very start of the validate_model_credentials method in core/plugin/impl/model.py: ```python if not credentials or all(not v for v in credentials.values()): return True ``` This will skip validation if credentials are empty and prevent the UnboundLocalError. After making this change, rebuild your API Docker image and restart the API container. This fix is confirmed by multiple sources and is the recommended workaround for this bug [(reference)](https://github.com/langgenius/dify/issues/27789#issuecomment-3483383413). If you’re using HTTPS endpoints with self-signed certificates, you may also need to disable certificate verification in the plugin code or import your LLM server’s cert into the plugin-daemon container to avoid related errors. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/b2441db6-9572-4e41-8e47-789065e71dd1?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/b2441db6-9572-4e41-8e47-789065e71dd1?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/b2441db6-9572-4e41-8e47-789065e71dd1?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/b2441db6-9572-4e41-8e47-789065e71dd1?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/b2441db6-9572-4e41-8e47-789065e71dd1?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/b2441db6-9572-4e41-8e47-789065e71dd1?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/b2441db6-9572-4e41-8e47-789065e71dd1?feedback_type=other)</sup> [![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=The%20error%20is%20still%20happening%20because%20the%20patch%20was%20only%20added%20to%20validate_provider_credentials%2C%20not%20to%20validate_model_credentials%E2%80%94which%20is%20the%20method%20actually%20used%20during%20the%20failing%20OpenAI-compatible%20add-on%20flow.%20To%20fix%20this%2C%20you%20need%20to%20add%20the%20following%20at%20the%20very%20start%20of%20the%20validate_model_credentials%20method%20in%20core/plugin/impl/model.py%3A%0A%0A%60%60%60python%0Aif%20not%20credentials%20or%20all%28not%20v%20for%20v%20in%20credentials.values%28%29%29%3A%0A%20%20%20%20return%20True%0A%60%60%60%0A%0AThis%20will%20skip%20validation%20if%20credentials%20are%20empty%20and%20prevent%20the%20UnboundLocalError.%20After%20making%20this%20change%2C%20rebuild%20your%20API%20Docker%20image%20and%20restart%20the%20API%20container.%20This%20fix%20is%20confirmed%20by%20multiple%20sources%20and%20is%20the%20recommended%20workaround%20for%20this%20bug%20%5B%28reference%29%5D%28https%3A//github.com/langgenius/dify/issues/27789%23issuecomment-3483383413%29.%0A%0AIf%20you%E2%80%99re%20using%20HTTPS%20endpoints%20with%20self-signed%20certificates%2C%20you%20may%20also%20need%20to%20disable%20certificate%20verification%20in%20the%20plugin%20code%20or%20import%20your%20LLM%20server%E2%80%99s%20cert%20into%20the%20plugin-daemon%20container%20to%20avoid%20related%20errors.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify-official-plugins/issues/2203)
Author
Owner

@bionexit commented on GitHub (Dec 8, 2025):

LLM back end startup script

python -m vllm.entrypoints.openai.api_server --model /models/Qwen3-235B-A22B-Instruct-2507 --port 30002 --tensor-parallel-size 8 --trust-remote-code --gpu-memory-utilization 0.975 --max-model-len 262144 --distributed-executor-backend=mp --enable-auto-tool-choice --tool-call-parser llama3_json --guided-decoding-backend xgrammar --api-key [api-key]

@dosu

this actions is done,still in error

if not credentials or all(not v for v in credentials.values()):
    return True
@bionexit commented on GitHub (Dec 8, 2025): LLM back end startup script ``` python -m vllm.entrypoints.openai.api_server --model /models/Qwen3-235B-A22B-Instruct-2507 --port 30002 --tensor-parallel-size 8 --trust-remote-code --gpu-memory-utilization 0.975 --max-model-len 262144 --distributed-executor-backend=mp --enable-auto-tool-choice --tool-call-parser llama3_json --guided-decoding-backend xgrammar --api-key [api-key] ``` @dosu this actions is done,still in error ``` if not credentials or all(not v for v in credentials.values()): return True ```
Author
Owner

@dosubot[bot] commented on GitHub (Dec 25, 2025):

Hi, @bionexit. I'm Dosu, and I'm helping the dify-official-plugins team manage their backlog and am marking this issue as stale.

Issue Summary:

  • You reported an UnboundLocalError when adding an OpenAI-compatible LLM in Dify 1.10.1-fix1 self-hosted via Docker.
  • The error stems from the plugin's credential validation code accessing an uninitialized variable.
  • A patch was recommended to modify validate_model_credentials to skip validation if credentials are empty.
  • You initially applied the patch to the wrong method but corrected it after clarification.
  • Despite applying the fix, errors persist, possibly related to HTTPS certificates or plugin-daemon container setup.

Next Steps:

  • Please confirm if this issue is still relevant with the latest version of dify-official-plugins by commenting here.
  • If I do not receive a response within 5 days, I will automatically close this issue.

Thank you for your understanding and contribution!

@dosubot[bot] commented on GitHub (Dec 25, 2025): Hi, @bionexit. I'm [Dosu](https://dosu.dev), and I'm helping the dify-official-plugins team manage their backlog and am marking this issue as stale. **Issue Summary:** - You reported an UnboundLocalError when adding an OpenAI-compatible LLM in Dify 1.10.1-fix1 self-hosted via Docker. - The error stems from the plugin's credential validation code accessing an uninitialized variable. - A patch was recommended to modify `validate_model_credentials` to skip validation if credentials are empty. - You initially applied the patch to the wrong method but corrected it after clarification. - Despite applying the fix, errors persist, possibly related to HTTPS certificates or plugin-daemon container setup. **Next Steps:** - Please confirm if this issue is still relevant with the latest version of dify-official-plugins by commenting here. - If I do not receive a response within 5 days, I will automatically close this issue. Thank you for your understanding and contribution!
Author
Owner

@realamd commented on GitHub (Jan 11, 2026):

In your docker-compose deployment, the backend code is inside the container image and not directly editable from the host. You have two options to apply the patch:

Option 1: Patch inside the running container (quick, but not persistent)

  1. Open a shell in the running API container:

    docker compose exec api /bin/bash
    

    (or use nerdctl compose exec api /bin/bash if you're using nerdctl)

  2. Find and edit the file:

    vi /app/api/core/plugin/impl/model.py
    

    Add this at the top of the validate_model_credentials method:
    if not credentials or all(not v for v in credentials.values()):
    return True

  3. Exit and restart the API container:

    docker compose restart api
    

    (or nerdctl compose restart api)

Note: This change will be lost if you update or recreate the container.

Option 2: Rebuild the image with your patch (persistent)

  1. Clone the Dify repo locally and make your code change in api/core/plugin/impl/model.py.

  2. Build a new image:

    docker build -t my-dify-api:patched ./api
    
  3. Edit your docker-compose.yaml to use my-dify-api:patched for the api service.

  4. Restart the stack:

    docker compose up -d --force-recreate api
    

    (or nerdctl compose up -d --force-recreate api)

After patching, retry adding your LLM and check the logs for errors. If you update Dify in the future, you’ll need to reapply your patch.

To reply, just mention @dosu.

How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Open in Cursor Join Discord Share on X

@dosu

Hi dosubot, I have applied the Option 2 and restart api successfully. But when I add local model, it still report the error.
What should I do?

Image
@realamd commented on GitHub (Jan 11, 2026): > In your docker-compose deployment, the backend code is inside the container image and not directly editable from the host. You have two options to apply the patch: > > **Option 1: Patch inside the running container (quick, but not persistent)** > > 1. Open a shell in the running API container: > ``` > docker compose exec api /bin/bash > ``` > > > > > > > > > > > > (or use `nerdctl compose exec api /bin/bash` if you're using nerdctl) > 2. Find and edit the file: > ``` > vi /app/api/core/plugin/impl/model.py > ``` > > > > > > > > > > > > Add this at the top of the `validate_model_credentials` method: > if not credentials or all(not v for v in credentials.values()): > return True > 3. Exit and restart the API container: > ``` > docker compose restart api > ``` > > > > > > > > > > > > (or `nerdctl compose restart api`) > > **Note:** This change will be lost if you update or recreate the container. > > **Option 2: Rebuild the image with your patch (persistent)** > > 1. Clone the Dify repo locally and make your code change in `api/core/plugin/impl/model.py`. > 2. Build a new image: > ``` > docker build -t my-dify-api:patched ./api > ``` > 3. Edit your `docker-compose.yaml` to use `my-dify-api:patched` for the `api` service. > 4. Restart the stack: > ``` > docker compose up -d --force-recreate api > ``` > > > > > > > > > > > > (or `nerdctl compose up -d --force-recreate api`) > > After patching, retry adding your LLM and check the logs for errors. If you update Dify in the future, you’ll need to reapply your patch. > > _To reply, just mention [@dosu](https://go.dosu.dev/dosubot)._ > > How did I do? [Good](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/d7385da9-93cd-4580-a5f1-8d2b43f09783?feedback_type=other) > > [![Open in Cursor](https://camo.githubusercontent.com/bdf7dbded65ee585887f47e5fd6fa099ea0933088b4b03d02e83b4def50154d4/68747470733a2f2f646f73752e6465762f646f73752d696e2d637572736f722e737667)](https://cursor.com/link/prompt?text=In%20your%20docker-compose%20deployment%2C%20the%20backend%20code%20is%20inside%20the%20container%20image%20and%20not%20directly%20editable%20from%20the%20host.%20You%20have%20two%20options%20to%20apply%20the%20patch%3A%0A%0A%2A%2AOption%201%3A%20Patch%20inside%20the%20running%20container%20%28quick%2C%20but%20not%20persistent%29%2A%2A%0A1.%20Open%20a%20shell%20in%20the%20running%20API%20container%3A%0A%20%20%20%60%60%60%0A%20%20%20docker%20compose%20exec%20api%20/bin/bash%0A%20%20%20%60%60%60%0A%20%20%20%28or%20use%20%60nerdctl%20compose%20exec%20api%20/bin/bash%60%20if%20you%27re%20using%20nerdctl%29%0A2.%20Find%20and%20edit%20the%20file%3A%0A%20%20%20%60%60%60%0A%20%20%20vi%20/app/api/core/plugin/impl/model.py%0A%20%20%20%60%60%60%0A%20%20%20Add%20this%20at%20the%20top%20of%20the%20%60validate_model_credentials%60%20method%3A%0A%20%20%20%60%60%60python%0A%20%20%20if%20not%20credentials%20or%20all%28not%20v%20for%20v%20in%20credentials.values%28%29%29%3A%0A%20%20%20%20%20%20%20return%20True%0A%20%20%20%60%60%60%0A3.%20Exit%20and%20restart%20the%20API%20container%3A%0A%20%20%20%60%60%60%0A%20%20%20docker%20compose%20restart%20api%0A%20%20%20%60%60%60%0A%20%20%20%28or%20%60nerdctl%20compose%20restart%20api%60%29%0A%0A%2A%2ANote%3A%2A%2A%20This%20change%20will%20be%20lost%20if%20you%20update%20or%20recreate%20the%20container.%0A%0A---%0A%0A%2A%2AOption%202%3A%20Rebuild%20the%20image%20with%20your%20patch%20%28persistent%29%2A%2A%0A1.%20Clone%20the%20Dify%20repo%20locally%20and%20make%20your%20code%20change%20in%20%60api/core/plugin/impl/model.py%60.%0A2.%20Build%20a%20new%20image%3A%0A%20%20%20%60%60%60%0A%20%20%20docker%20build%20-t%20my-dify-api%3Apatched%20./api%0A%20%20%20%60%60%60%0A3.%20Edit%20your%20%60docker-compose.yaml%60%20to%20use%20%60my-dify-api%3Apatched%60%20for%20the%20%60api%60%20service.%0A4.%20Restart%20the%20stack%3A%0A%20%20%20%60%60%60%0A%20%20%20docker%20compose%20up%20-d%20--force-recreate%20api%0A%20%20%20%60%60%60%0A%20%20%20%28or%20%60nerdctl%20compose%20up%20-d%20--force-recreate%20api%60%29%0A%0A---%0A%0AAfter%20patching%2C%20retry%20adding%20your%20LLM%20and%20check%20the%20logs%20for%20errors.%20If%20you%20update%20Dify%20in%20the%20future%2C%20you%E2%80%99ll%20need%20to%20reapply%20your%20patch.) [![Join Discord](https://camo.githubusercontent.com/7d2066700925db1e370d956834f9ea0e5bc92cecbe84963fbd2a363e45091b4e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6a6f696e2d3538363546323f6c6f676f3d646973636f7264266c6f676f436f6c6f723d7768697465266c6162656c3d)](https://go.dosu.dev/discord-bot) [![Share on X](https://camo.githubusercontent.com/a8bd7f3fcf3f5e3bd124eee9ae50ae2ac17b40971726665ac2121d48f9aee155/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f582d73686172652d626c61636b)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify-official-plugins/issues/2203) [@dosu](https://go.dosu.dev/dosubot) Hi dosubot, I have applied the Option 2 and restart api successfully. But when I add local model, it still report the error. What should I do? <img width="1334" height="833" alt="Image" src="https://github.com/user-attachments/assets/4df9d79a-dc0a-4f68-a933-6741fed5b012" />
Author
Owner

@Alvs10735 commented on GitHub (Feb 9, 2026):

I've got the same error

dify
Version1.12.1

plugin OpenAI-API-compatible
version 0.0.34

I have used Option 2
error still the same

@Alvs10735 commented on GitHub (Feb 9, 2026): I've got the same error dify Version1.12.1 plugin OpenAI-API-compatible version 0.0.34 I have used Option 2 error still the same
Author
Owner

@bionexit commented on GitHub (Feb 9, 2026):

I've got the same error

dify Version1.12.1

plugin OpenAI-API-compatible version 0.0.34

I have used Option 2 error still the same

Run a curl for a post requst to the Llm server within credential inside the docker. my error happened due to network policy block the connection.

Wish help.

@bionexit commented on GitHub (Feb 9, 2026): > I've got the same error > > dify Version1.12.1 > > plugin OpenAI-API-compatible version 0.0.34 > > I have used Option 2 error still the same Run a curl for a post requst to the Llm server within credential inside the docker. my error happened due to network policy block the connection. Wish help.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify-official-plugins#860