This is an automated email from the ASF dual-hosted git repository.
piotr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git
The following commit(s) were added to refs/heads/master by this push:
new db105ddbf fix(connectors): harden plugin loading and config metadata
(#2713)
db105ddbf is described below
commit db105ddbf064af9a009317686a6b3b7765d5f369
Author: Hubert Gruszecki <[email protected]>
AuthorDate: Tue Feb 10 14:43:17 2026 +0100
fix(connectors): harden plugin loading and config metadata (#2713)
Fall back to modified() when created() is unsupported (XFS,
Overlay2). Replace .expect() panics with proper error propagation
in config loading and path conversion.
Rewrite resolve_plugin_path to return Result and search multiple
directories (binary dir, cwd, /usr/lib, /usr/lib64, /lib, /lib64,
/usr/local/lib, /usr/local/lib64) with actionable diagnostics
when the library is not found. Add unit tests for resolution.
Rename example configs to {name}_{type}[_v{N}].toml convention
and add missing example configs for elasticsearch and postgres
connectors. Switch all connector config.toml paths from debug
to release builds. Update READMEs with plugin path resolution
docs and new config filenames. Remove WiP notice.
Bump version to 0.2.4-edge.1.
Fixes #2712
---
Cargo.lock | 2 +-
DEPENDENCIES.md | 2 +-
core/connectors/README.md | 30 +++-
core/connectors/runtime/Cargo.toml | 2 +-
.../connectors/{iceberg.toml => iceberg_sink.toml} | 1 +
.../{quickwit.toml => quickwit_sink.toml} | 1 +
.../{random_v0.toml => random_source_v0.toml} | 0
.../{random_v1.toml => random_source_v1.toml} | 0
.../connectors/{stdout.toml => stdout_sink.toml} | 3 +-
.../src/configs/connectors/local_provider.rs | 27 +++-
core/connectors/runtime/src/main.rs | 162 +++++++++++++++++++--
core/connectors/runtime/src/sink.rs | 2 +-
core/connectors/runtime/src/source.rs | 2 +-
core/connectors/sinks/README.md | 2 +-
.../sinks/elasticsearch_sink/config.toml | 2 +-
core/connectors/sinks/iceberg_sink/config.toml | 2 +-
core/connectors/sinks/postgres_sink/config.toml | 2 +-
core/connectors/sinks/quickwit_sink/config.toml | 2 +-
core/connectors/sinks/stdout_sink/config.toml | 2 +-
core/connectors/sources/README.md | 2 +-
.../sources/elasticsearch_source/config.toml | 2 +-
.../connectors/sources/postgres_source/config.toml | 2 +-
core/connectors/sources/random_source/config.toml | 2 +-
23 files changed, 222 insertions(+), 32 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 0d5781ce3..4dbeac128 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4525,7 +4525,7 @@ dependencies = [
[[package]]
name = "iggy-connectors"
-version = "0.2.3-edge.1"
+version = "0.2.4-edge.1"
dependencies = [
"async-trait",
"axum",
diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md
index be466b0d5..d61604cda 100644
--- a/DEPENDENCIES.md
+++ b/DEPENDENCIES.md
@@ -388,7 +388,7 @@ iggy: 0.8.3-edge.1, "Apache-2.0",
iggy-bench: 0.3.3-edge.1, "Apache-2.0",
iggy-bench-dashboard-server: 0.5.1-edge.1, "Apache-2.0",
iggy-cli: 0.10.3-edge.1, "Apache-2.0",
-iggy-connectors: 0.2.3-edge.1, "Apache-2.0",
+iggy-connectors: 0.2.4-edge.1, "Apache-2.0",
iggy-mcp: 0.2.3-edge.1, "Apache-2.0",
iggy_binary_protocol: 0.8.3-edge.1, "Apache-2.0",
iggy_common: 0.8.3-edge.1, "Apache-2.0",
diff --git a/core/connectors/README.md b/core/connectors/README.md
index 46729ec7d..cdef67789 100644
--- a/core/connectors/README.md
+++ b/core/connectors/README.md
@@ -2,8 +2,6 @@
The highly performant and modular runtime for statically typed, yet
dynamically loaded connectors. Ingest the data from the external sources and
push it further to the Iggy streams, or fetch the data from the Iggy streams
and push it further to the external sources. Create your own Rust plugins by
simply implementing either the `Source` or `Sink` trait and build custom
pipelines for the data processing.
-**This is still WiP, and the runtime can be started only after compilation
from the source code (no installable package yet).**
-
The [docker image](https://hub.docker.com/r/apache/iggy-connect) is available,
and can be fetched via `docker pull apache/iggy-connect`.
## Features
@@ -20,7 +18,7 @@ The [docker
image](https://hub.docker.com/r/apache/iggy-connect) is available, a
## Quick Start
-1. Build the project in release mode (or debug, and update the connectors
paths in the config accordingly), and make sure that the plugins specified in
`core/connectors/runtime/example_config/connectors/` directory under `path` are
available. The configuration must be provided in `toml` format.
+1. Build the project in release mode (or debug, and update the connectors
paths in the config accordingly), and make sure that the plugins specified in
`core/connectors/runtime/example_config/connectors/` directory under `path` are
available. The configuration must be provided in `toml` format, with files
following the `{connector_name}_{type}[_v{N}].toml` naming convention.
2. Run `docker compose up -d` from `/examples/rust/src/sink-data-producer`
which will start the Quickwit server to be used by an example sink connector.
At this point, you can access the Quickwit UI at
[http://localhost:7280](http://localhost:7280) - check this dashboard again
later on, after the `events` index will be created.
@@ -43,6 +41,32 @@ The [docker
image](https://hub.docker.com/r/apache/iggy-connect) is available, a
All the connectors are implemented as Rust libraries and can be used as a part
of the connector runtime. The runtime is responsible for managing the lifecycle
of the connectors and providing the necessary infrastructure for the connectors
to run. For more information, please refer to the **[runtime
documentation](https://github.com/apache/iggy/tree/master/core/connectors/runtime)**.
+## Plugin path resolution
+
+The `path` field in connector configs points to the shared library (`.so`,
`.dylib`, `.dll`). The runtime resolves it as follows:
+
+1. **Extension** — if the path has no recognized extension, the OS-native one
is appended automatically (`.so` on Linux, `.dylib` on macOS, `.dll` on
Windows).
+
+2. **Absolute paths** — used as-is.
+
+3. **Relative paths** — searched in order, returning the first match:
+ - the literal relative path (from working directory)
+ - directory of the runtime binary (filename only)
+ - current working directory (filename only)
+ - `/usr/lib`, `/usr/lib64`, `/lib`, `/lib64`, `/usr/local/lib`,
`/usr/local/lib64`
+
+**Examples:**
+
+```toml
+# Relative — resolved against search dirs; extension appended on Linux
+path = "target/release/libiggy_connector_stdout_sink"
+
+# Absolute — used directly
+path = "/opt/iggy/plugins/libiggy_connector_stdout_sink.so"
+```
+
+If the library is not found, the runtime logs all searched paths to help
diagnose the issue.
+
## Sink
Sinks are responsible for consuming the messages from the configured stream(s)
and topic(s) and sending them further to the specified destination. For
example, the Quickwit sink connector is responsible for sending the messages to
the Quickwit indexer.
diff --git a/core/connectors/runtime/Cargo.toml
b/core/connectors/runtime/Cargo.toml
index 8e38283f3..962c319c2 100644
--- a/core/connectors/runtime/Cargo.toml
+++ b/core/connectors/runtime/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "iggy-connectors"
-version = "0.2.3-edge.1"
+version = "0.2.4-edge.1"
description = "Connectors runtime for Iggy message streaming platform"
edition = "2024"
license = "Apache-2.0"
diff --git a/core/connectors/runtime/example_config/connectors/iceberg.toml
b/core/connectors/runtime/example_config/connectors/iceberg_sink.toml
similarity index 98%
rename from core/connectors/runtime/example_config/connectors/iceberg.toml
rename to core/connectors/runtime/example_config/connectors/iceberg_sink.toml
index 2eaff0dbb..9228be1de 100644
--- a/core/connectors/runtime/example_config/connectors/iceberg.toml
+++ b/core/connectors/runtime/example_config/connectors/iceberg_sink.toml
@@ -21,6 +21,7 @@ enabled = true
version = 0
name = "Iceberg sink"
path = "target/release/libiggy_connector_iceberg_sink"
+verbose = false
[[streams]]
stream = "example_stream"
diff --git a/core/connectors/runtime/example_config/connectors/quickwit.toml
b/core/connectors/runtime/example_config/connectors/quickwit_sink.toml
similarity index 99%
rename from core/connectors/runtime/example_config/connectors/quickwit.toml
rename to core/connectors/runtime/example_config/connectors/quickwit_sink.toml
index 5b6abd83e..e4622ffcf 100644
--- a/core/connectors/runtime/example_config/connectors/quickwit.toml
+++ b/core/connectors/runtime/example_config/connectors/quickwit_sink.toml
@@ -22,6 +22,7 @@ version = 0
name = "Quickwit sink 1"
path = "target/release/libiggy_connector_quickwit_sink"
plugin_config_format = "yaml"
+verbose = false
[[streams]]
stream = "qw"
diff --git a/core/connectors/runtime/example_config/connectors/random_v0.toml
b/core/connectors/runtime/example_config/connectors/random_source_v0.toml
similarity index 100%
rename from core/connectors/runtime/example_config/connectors/random_v0.toml
rename to
core/connectors/runtime/example_config/connectors/random_source_v0.toml
diff --git a/core/connectors/runtime/example_config/connectors/random_v1.toml
b/core/connectors/runtime/example_config/connectors/random_source_v1.toml
similarity index 100%
rename from core/connectors/runtime/example_config/connectors/random_v1.toml
rename to
core/connectors/runtime/example_config/connectors/random_source_v1.toml
diff --git a/core/connectors/runtime/example_config/connectors/stdout.toml
b/core/connectors/runtime/example_config/connectors/stdout_sink.toml
similarity index 97%
rename from core/connectors/runtime/example_config/connectors/stdout.toml
rename to core/connectors/runtime/example_config/connectors/stdout_sink.toml
index c74a5820d..913993827 100644
--- a/core/connectors/runtime/example_config/connectors/stdout.toml
+++ b/core/connectors/runtime/example_config/connectors/stdout_sink.toml
@@ -21,6 +21,7 @@ enabled = true
version = 0
name = "Stdout sink"
path = "target/release/libiggy_connector_stdout_sink"
+verbose = false
[[streams]]
stream = "example_stream"
@@ -31,7 +32,7 @@ poll_interval = "5ms"
consumer_group = "stdout_sink_connector"
[plugin_config]
-print_payload = false
+print_payload = true
[transforms.add_fields]
enabled = true
diff --git a/core/connectors/runtime/src/configs/connectors/local_provider.rs
b/core/connectors/runtime/src/configs/connectors/local_provider.rs
index 801eff73a..5080d796d 100644
--- a/core/connectors/runtime/src/configs/connectors/local_provider.rs
+++ b/core/connectors/runtime/src/configs/connectors/local_provider.rs
@@ -198,15 +198,34 @@ impl LocalConnectorsConfigProvider<Created> {
debug!("Loaded base configuration: {:?}", base_config);
let path = path
.to_str()
- .expect("Failed to convert connector configuration path to
string")
+ .ok_or_else(|| {
+ RuntimeError::InvalidConfiguration(format!(
+ "Non-UTF8 connector config path: {}",
+ path.display()
+ ))
+ })?
.to_string();
let connector_config: ConnectorConfig =
Self::create_file_config_provider(path.clone(),
&base_config)
.load_config()
.await
- .expect("Failed to load connector configuration");
-
- let created_at: DateTime<Utc> =
entry.metadata()?.created()?.into();
+ .map_err(|e| {
+ RuntimeError::InvalidConfiguration(format!(
+ "Failed to load connector configuration from
'{path}': {e}"
+ ))
+ })?;
+
+ let metadata = entry.metadata()?;
+ let created_at: DateTime<Utc> = metadata
+ .created()
+ .or_else(|_| metadata.modified())
+ .map(Into::into)
+ .unwrap_or_else(|_| {
+ warn!(
+ "Could not read created or modified time for
'{path}', using current time",
+ );
+ Utc::now()
+ });
let connector_id: ConnectorId = (&connector_config).into();
let version = connector_config.version();
diff --git a/core/connectors/runtime/src/main.rs
b/core/connectors/runtime/src/main.rs
index 5d55be603..72896d9f5 100644
--- a/core/connectors/runtime/src/main.rs
+++ b/core/connectors/runtime/src/main.rs
@@ -40,7 +40,7 @@ use std::{
env,
sync::{Arc, atomic::AtomicU32},
};
-use tracing::{debug, info};
+use tracing::info;
mod api;
pub(crate) mod configs;
@@ -266,21 +266,103 @@ async fn main() -> Result<(), RuntimeError> {
Ok(())
}
-pub(crate) fn resolve_plugin_path(path: &str) -> String {
- let extension = path.split('.').next_back().unwrap_or_default();
- if ALLOWED_PLUGIN_EXTENSIONS.contains(&extension) {
+/// Resolves a plugin shared library path from the connector config `path`
field.
+///
+/// Accepts both `plugin.so` and `plugin` (OS-specific extension appended if
missing).
+/// For absolute paths, checks existence at the literal location.
+/// For relative paths, searches in order:
+/// 1. Literal path (relative to working directory)
+/// 2. Directory of the runtime binary
+/// 3. Current working directory (filename only)
+/// 4. /usr/lib
+/// 5. /usr/lib64
+/// 6. /lib
+/// 7. /lib64
+/// 8. /usr/local/lib
+/// 9. /usr/local/lib64
+pub(crate) fn resolve_plugin_path(path: &str) -> Result<String, RuntimeError> {
+ let extension = std::path::Path::new(path)
+ .extension()
+ .and_then(|e| e.to_str())
+ .unwrap_or_default();
+ let with_extension = if ALLOWED_PLUGIN_EXTENSIONS.contains(&extension) {
path.to_string()
} else {
- let os = std::env::consts::OS;
- let os_extension = match os {
- "windows" => "dll",
+ let os_extension = match std::env::consts::OS {
"macos" => "dylib",
+ "windows" => "dll",
_ => "so",
};
-
- debug!("Resolved plugin path: {path}.{os_extension} for detected OS:
{os}");
format!("{path}.{os_extension}")
+ };
+
+ let candidate = std::path::Path::new(&with_extension);
+
+ if candidate.exists() {
+ info!("Resolved plugin path: {with_extension}");
+ return Ok(with_extension);
}
+
+ if candidate.is_relative() {
+ let Some(file_name) = candidate.file_name() else {
+ return Err(RuntimeError::InvalidConfiguration(format!(
+ "Invalid plugin path: '{with_extension}'"
+ )));
+ };
+
+ let search_dirs: Vec<std::path::PathBuf> = [
+ std::env::current_exe()
+ .ok()
+ .and_then(|p| p.parent().map(|d| d.to_path_buf())),
+ std::env::current_dir().ok(),
+ Some(std::path::PathBuf::from("/usr/lib")),
+ Some(std::path::PathBuf::from("/usr/lib64")),
+ Some(std::path::PathBuf::from("/lib")),
+ Some(std::path::PathBuf::from("/lib64")),
+ Some(std::path::PathBuf::from("/usr/local/lib")),
+ Some(std::path::PathBuf::from("/usr/local/lib64")),
+ ]
+ .into_iter()
+ .flatten()
+ .collect();
+
+ for dir in &search_dirs {
+ let full = dir.join(file_name);
+ if full.exists() {
+ let resolved = match full.to_str() {
+ Some(s) => s.to_owned(),
+ None => continue,
+ };
+ info!(
+ "Resolved plugin path: {resolved} (found in {})",
+ dir.display()
+ );
+ return Ok(resolved);
+ }
+ }
+
+ let searched: Vec<String> = std::iter::once(with_extension.clone())
+ .chain(search_dirs.iter().filter_map(|d| {
+ let full = d.join(file_name);
+ full.to_str().map(|s| s.to_owned())
+ }))
+ .collect();
+
+ return Err(RuntimeError::InvalidConfiguration(format!(
+ "Plugin library not found. Searched paths:\n{}\n\
+ Ensure the shared library (.so/.dylib/.dll) is built and placed
in one of these locations.",
+ searched
+ .iter()
+ .map(|p| format!(" - {p}"))
+ .collect::<Vec<_>>()
+ .join("\n")
+ )));
+ }
+
+ Err(RuntimeError::InvalidConfiguration(format!(
+ "Plugin library not found at '{with_extension}'. \
+ Ensure the shared library file exists at this path."
+ )))
}
struct SinkConnector {
@@ -350,3 +432,65 @@ struct SourceConnectorWrapper {
callback: HandleCallback,
plugins: Vec<SourceConnectorPlugin>,
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::fs;
+ use tempfile::TempDir;
+
+ #[test]
+ fn path_with_known_extension_is_preserved() {
+ let result = resolve_plugin_path("/tmp/nonexistent_test_plugin.so");
+ let err = result.unwrap_err().to_string();
+ assert!(
+ err.contains("nonexistent_test_plugin.so"),
+ "Error should mention the .so path, got: {err}"
+ );
+ }
+
+ #[test]
+ fn path_without_extension_gets_os_suffix() {
+ let result = resolve_plugin_path("/tmp/nonexistent_test_plugin");
+ let err = result.unwrap_err().to_string();
+ let expected_ext = match std::env::consts::OS {
+ "macos" => "dylib",
+ _ => "so",
+ };
+ assert!(
+ err.contains(&format!("nonexistent_test_plugin.{expected_ext}")),
+ "Error should mention OS-specific extension, got: {err}"
+ );
+ }
+
+ #[test]
+ fn nonexistent_relative_path_lists_searched_locations() {
+ let result = resolve_plugin_path("nonexistent_test_plugin.so");
+ let err = result.unwrap_err().to_string();
+ assert!(
+ err.contains("Searched paths:"),
+ "Should list searched paths, got: {err}"
+ );
+ }
+
+ #[test]
+ fn nonexistent_absolute_path_returns_specific_error() {
+ let result = resolve_plugin_path("/no/such/dir/plugin.so");
+ let err = result.unwrap_err().to_string();
+ assert!(
+ err.contains("/no/such/dir/plugin.so"),
+ "Should mention the exact path, got: {err}"
+ );
+ }
+
+ #[test]
+ fn existing_file_resolves_directly() {
+ let dir = TempDir::new().unwrap();
+ let plugin_path = dir.path().join("test_plugin.so");
+ fs::write(&plugin_path, b"fake-plugin").unwrap();
+
+ let result = resolve_plugin_path(plugin_path.to_str().unwrap())
+ .expect("should resolve existing file");
+ assert_eq!(result, plugin_path.to_str().unwrap());
+ }
+}
diff --git a/core/connectors/runtime/src/sink.rs
b/core/connectors/runtime/src/sink.rs
index 092e41680..fb53cdb50 100644
--- a/core/connectors/runtime/src/sink.rs
+++ b/core/connectors/runtime/src/sink.rs
@@ -57,7 +57,7 @@ pub async fn init(
}
let plugin_id = PLUGIN_ID.fetch_add(1, Ordering::SeqCst);
- let path = resolve_plugin_path(&config.path);
+ let path = resolve_plugin_path(&config.path)?;
info!(
"Initializing sink container with name: {name} ({key}), config
version: {}, plugin: {path}",
&config.version
diff --git a/core/connectors/runtime/src/source.rs
b/core/connectors/runtime/src/source.rs
index b665a1310..889932ecb 100644
--- a/core/connectors/runtime/src/source.rs
+++ b/core/connectors/runtime/src/source.rs
@@ -67,7 +67,7 @@ pub async fn init(
}
let plugin_id = PLUGIN_ID.fetch_add(1, Ordering::SeqCst);
- let path = resolve_plugin_path(&config.path);
+ let path = resolve_plugin_path(&config.path)?;
info!(
"Initializing source container with name: {name} ({key}), config
version: {}, plugin: {path}",
&config.version
diff --git a/core/connectors/sinks/README.md b/core/connectors/sinks/README.md
index 678bb651d..55c639c33 100644
--- a/core/connectors/sinks/README.md
+++ b/core/connectors/sinks/README.md
@@ -62,7 +62,7 @@ config_type = "local"
config_dir = "path/to/connectors"
```
-**Sink connector config (connectors/stdout.toml):**
+**Sink connector config (connectors/stdout_sink.toml):**
```toml
# Type of connector (sink or source)
diff --git a/core/connectors/sinks/elasticsearch_sink/config.toml
b/core/connectors/sinks/elasticsearch_sink/config.toml
index 90dc6faa9..171e0eec6 100644
--- a/core/connectors/sinks/elasticsearch_sink/config.toml
+++ b/core/connectors/sinks/elasticsearch_sink/config.toml
@@ -20,7 +20,7 @@ key = "elasticsearch"
enabled = true
version = 0
name = "Elasticsearch sink"
-path = "../../target/debug/libiggy_connector_elasticsearch_sink"
+path = "../../target/release/libiggy_connector_elasticsearch_sink"
verbose = false
[[streams]]
diff --git a/core/connectors/sinks/iceberg_sink/config.toml
b/core/connectors/sinks/iceberg_sink/config.toml
index 702b7aa57..3a8b21596 100644
--- a/core/connectors/sinks/iceberg_sink/config.toml
+++ b/core/connectors/sinks/iceberg_sink/config.toml
@@ -20,7 +20,7 @@ key = "iceberg"
enabled = true
version = 0
name = "Iceberg sink"
-path = "../../target/debug/libiggy_connector_iceberg_sink"
+path = "../../target/release/libiggy_connector_iceberg_sink"
verbose = true
[[streams]]
diff --git a/core/connectors/sinks/postgres_sink/config.toml
b/core/connectors/sinks/postgres_sink/config.toml
index aea049a53..3fe8987b8 100644
--- a/core/connectors/sinks/postgres_sink/config.toml
+++ b/core/connectors/sinks/postgres_sink/config.toml
@@ -20,7 +20,7 @@ key = "postgres"
enabled = true
version = 0
name = "Postgres sink"
-path = "../../target/debug/libiggy_connector_postgres_sink"
+path = "../../target/release/libiggy_connector_postgres_sink"
verbose = false
[[streams]]
diff --git a/core/connectors/sinks/quickwit_sink/config.toml
b/core/connectors/sinks/quickwit_sink/config.toml
index fab316524..205c37268 100644
--- a/core/connectors/sinks/quickwit_sink/config.toml
+++ b/core/connectors/sinks/quickwit_sink/config.toml
@@ -20,7 +20,7 @@ key = "quickwit"
enabled = true
version = 0
name = "Quickwit sink"
-path = "../../target/debug/libiggy_connector_quickwit_sink"
+path = "../../target/release/libiggy_connector_quickwit_sink"
verbose = false
[[streams]]
diff --git a/core/connectors/sinks/stdout_sink/config.toml
b/core/connectors/sinks/stdout_sink/config.toml
index cc1dda333..ae9708426 100644
--- a/core/connectors/sinks/stdout_sink/config.toml
+++ b/core/connectors/sinks/stdout_sink/config.toml
@@ -20,7 +20,7 @@ key = "stdout"
enabled = true
version = 0
name = "Stdout sink"
-path = "../../target/debug/libiggy_connector_stdout_sink"
+path = "../../target/release/libiggy_connector_stdout_sink"
verbose = true
[[streams]]
diff --git a/core/connectors/sources/README.md
b/core/connectors/sources/README.md
index 378e54044..3f45e149a 100644
--- a/core/connectors/sources/README.md
+++ b/core/connectors/sources/README.md
@@ -55,7 +55,7 @@ config_type = "local"
config_dir = "path/to/connectors"
```
-**Source connector config (connectors/random.toml):**
+**Source connector config (connectors/random_source_v0.toml):**
```toml
# Type of connector (sink or source)
diff --git a/core/connectors/sources/elasticsearch_source/config.toml
b/core/connectors/sources/elasticsearch_source/config.toml
index d4e5bceba..c58b76382 100644
--- a/core/connectors/sources/elasticsearch_source/config.toml
+++ b/core/connectors/sources/elasticsearch_source/config.toml
@@ -20,7 +20,7 @@ key = "elasticsearch"
enabled = true
version = 0
name = "Elasticsearch source"
-path = "../../target/debug/libiggy_connector_elasticsearch_source"
+path = "../../target/release/libiggy_connector_elasticsearch_source"
plugin_config_format = "json"
[[streams]]
diff --git a/core/connectors/sources/postgres_source/config.toml
b/core/connectors/sources/postgres_source/config.toml
index ca809f2b8..1ea3757f2 100644
--- a/core/connectors/sources/postgres_source/config.toml
+++ b/core/connectors/sources/postgres_source/config.toml
@@ -20,7 +20,7 @@ key = "postgres"
enabled = true
version = 0
name = "Postgres source"
-path = "../../target/debug/libiggy_connector_postgres_source"
+path = "../../target/release/libiggy_connector_postgres_source"
verbose = false
[[streams]]
diff --git a/core/connectors/sources/random_source/config.toml
b/core/connectors/sources/random_source/config.toml
index fb219ab7e..ed972f5fc 100644
--- a/core/connectors/sources/random_source/config.toml
+++ b/core/connectors/sources/random_source/config.toml
@@ -20,7 +20,7 @@ key = "random"
enabled = true
version = 0
name = "Random source"
-path = "../../target/debug/libiggy_connector_random_source"
+path = "../../target/release/libiggy_connector_random_source"
plugin_config_format = "json"
[[streams]]