New to Kestra?
Use blueprints to kickstart your first workflows.
Kestra flow that validates a CSV in two stages inside a WorkingDirectory, a bash row-count check then a pandas required-columns check, with scripts inlined via inputFiles.
Bad files should fail loudly at the front door, not three tasks deep into a load. This Kestra blueprint runs a two-stage validation gate inside a single working directory: a bash script does the cheap structural checks (file exists, rows present, header preview), then a Python script loads the file with pandas and fails the execution if required columns are missing. Both scripts are inlined through inputFiles, so the flow deploys and runs on any Kestra instance with nothing to sync first.
my_working_dir task (io.kestra.plugin.core.flow.WorkingDirectory) gives all child tasks one shared filesystem, following the one-working-directory-per-flow best practice.create_csv task (io.kestra.plugin.core.storage.Write) writes a sample users CSV to internal storage; in production you would replace this with your real extract.shell_check task (io.kestra.plugin.scripts.shell.Commands) receives check.sh via inputFiles and runs it with the CSV's URI as argument. Kestra materializes internal storage URIs referenced in commands as local files, so the script just reads a path. It prints line counts and the header, and exits non-zero on a missing file.python_validate task (io.kestra.plugin.scripts.python.Commands) runs pre_process.py in a python:3.13-slim container with pandas and click declared as dependencies. The click CLI takes --input-file and --column-names, logs row and column stats, and raises if any required column is absent, failing the task and therefore the flow.inputFiles for namespaceFiles once the scripts live as namespace files synced from Git.Validation scripts scattered across servers fail silently or, worse, get skipped. In Kestra each check is a task with its own logs, exit-code semantics, and container image, and the working directory plus internal storage handle file movement without shared volumes or scp. Declaring dependencies on the Python task replaces requirements.txt shipping, and the whole gate is versioned YAML: review it, revision it, and reuse it as a subflow in every ingestion pipeline you own.
python:3.13-slim container.No secrets are required. If the real CSV comes from an authenticated source, fetch it with a dedicated task using {{ secret('NAME') }} credentials and pass its URI to the validators.
company.team namespace and execute it.shell_check logs for the row count and header, then python_validate logs for the pandas column report.email from the create_csv header and rerun to watch the Python stage fail with a precise error.create_csv with your real file source and update --column-names to your schema.io.kestra.plugin.git.SyncNamespaceFiles, then reference them with namespaceFiles.enabled: true and an include list instead of inputFiles.--column-names with a flow input so different callers validate different schemas.errors branch with a Slack or email task so producers hear about bad files immediately.