Next.XP Upgrading Issues

Enonic version: 7.13.5


after Upgrading Next.XP to 2.0 following the documentation for upgrading Guillotine and Upgrading XP to 7.13.5 along with ContentStudio to 5.1.3 , I have 2 issues:

  1. Images are not rendered in Content Studio. In Preview I get an 401-Unauthorized
  2. I get an error for a scheduled tasks (BUG ?)
com.enonic.xp.task.TaskNotFoundException: Task [] not found. Missing task script

The task script is unchanged !

Hello @luctho !

I can try to look into the first one, and maybe @rymsha knows something about the second ?

Did you remember to update next.xp app for Enonic XP as well to version 2 ?
If yes, I’m going to need logs from both XP and next.js servers.

But before doing that, enable debug logging for next.xp app by doing the following:

  • go into <xp-home>/config/ folder
  • edit logback.xml file
  • add following lines:
  <logger name="" level="debug" additivity="false">
    <appender-ref ref="STDOUT"/>
  • if you don’t have one, create it with following contents:
<configuration scan="true" scanPeriod="60 seconds"> 
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
      <pattern>%magenta(%date{HH:mm:ss.SSS}) %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>

  <root level="info"> 
    <appender-ref ref="STDOUT"/>
    <appender-ref ref="FILE"/>

  <logger name="" level="debug" additivity="false">
    <appender-ref ref="STDOUT"/>


Hi Pavel (@pmi) ,

i have Version 2 of the app installed!

you can download a fresh logfile here:


Means that you don’t have a js file for the task.


There is nothing wrong about access in xp logs, but try checking the following:

If you have following ENONIC_API in your .env file:


Then try accessing the same domain in your browser as well



Because browser considers and localhost as different domains and might not include authorization cookies with requests for images

@pmi : that solved my issue ! Thx

@rymsha : The file fetch-market-news.js is part of my build folder !?

I converted this APP to webpack - the non webpack version works ! Maybe a webpack-config issue ???

Make sure fetch-market-news.js file is insude app jar.
Make sure it exports run finction = function ...

Hi Sergey,

both criterias are met :frowning:
Before I converted the app to a webpack-solution - the tasks was running without any issues.

The only other thing I changed is the project- as the default project is disabled by default.
But as far as I know, that should not make a difference - does it?

In addition to that , the task is displayed in Applications-view:

How do the contents of the JS file look like? Make sure that Webpack builds it in CJS (CommonJS) format, not ESM (EcmaScript Modules).

Here is the code (maybe this helps in analyse)

const taskLib = require('/lib/xp/task');
const feedUtils = require('/lib/feedUtils');
const httpClient = require("/lib/http-client");
const contentLib = require('/lib/xp/content');
const contextLib = require('/lib/xp/context'); = function (params) {

    taskLib.progress({info: 'Task started'});"Start task with the following params %s", params);

    const NEWS_API_URL = params.api_url;
    const NEWS_FOLDER = params.news_folder;
    const ROOT_PATH = params.root_path;
    const REPOSITORY = params.repository;

    if (!NEWS_API_URL) {
        log.warning("You must specify an url in %S", + '.cfg');

    // fetch the news from the given url
    let newsResponse;
    try {
        newsResponse = httpClient.request({
            url: NEWS_API_URL
    } catch (e) {
        log.error("Failed to fetch news from %s with the following message: %s", NEWS_API_URL,;
        taskLib.progress({info: 'Task aborted'});

    // exit function, when status not 200
    if (newsResponse.status !== 200) {
        log.warning('url %s responded with status %s', NEWS_API_URL, newsResponse.status);
        taskLib.progress({info: 'Task aborted'});

    const newsItems = JSON.parse(newsResponse.body).items;

    let newsCount;
    newsItems ? newsCount = newsItems.length : newsCount = 0;`Es wurden ${newsCount} Nachrichten gelesen`);

    const newsFolderExists = runInContext(
        () => checkFolderExists(ROOT_PATH + '/' + NEWS_FOLDER));
    if (!newsFolderExists) {"Create Market News Folder")
        //create folder
            () => createDirectoryInRepo(

    let folderCreated = 0;
    let newsCreated = 0;, i) => {
        const content = newsItems[i].content;

        // extract image from content
        // mostly higher resolution that what is in image
        const imgSrc = feedUtils.extractImg(content);

        // check image src and override image
        if (imgSrc) {
            newsItems[i].image = imgSrc;

        //ensure that image url is encrypted
        //to prevent browser warnings
        newsItems[i].image = newsItems[i].image.replace("http:", "https:");

        //remove image, anchors and line-breaks
        newsItems[i].content = feedUtils.cleanContent(content);

        //convert date
        const date = new Date(newsItems[i].pubDate);
        newsItems[i].pubDate = date.toISOString();

        //get year and month in 2-digit format from date
        const year = date.getFullYear().toString();
        const month = ("0" + (date.getMonth() + 1)).slice(-2);

        //prepare folders for news
        //follows site/news/year/month
        folderCreated += runInContext(
            () => createDirectoryInRepo(ROOT_PATH + '/' + NEWS_FOLDER, year, year),
        folderCreated += runInContext(
            () => createDirectoryInRepo(`${ROOT_PATH}/${NEWS_FOLDER}/${year}`, month, `${month}/${year}`),

        //finally, save the news-article in repo
        newsCreated += runInContext(
            () => saveToRepo(item, NEWS_FOLDER, ROOT_PATH),
    });"NEWS-FETCHER: Created %s folders and %s news", folderCreated, newsCreated);

    taskLib.progress({info: 'Task completed'});

 * creates sub-folders in repository
 * @param baseDir path to create the folder in
 * @param dirName name of the folder to create
 * @param displayName name to show in UI
 * @param templateId id of the page-template
function createDirectoryInRepo(baseDir, dirName, displayName) {

    try {
        const folder = contentLib.create({
            name: dirName,
            displayName: displayName,
            contentType: `${}:marketNewsFolder`,
            parentPath: baseDir,
            data: "",
        })"+++ created a new folder: %s +++", baseDir + '/' + dirName);
        return 1;

    } catch
        (e) {
        if (e.code === 'contentAlreadyExists') {
            return 0;
        } else {
            log.error('Unexpected error: (%s) %s ', e.code, e.message);
            return 0;

function addImageNode(node) {
    const imgSrc =;
    if (!imgSrc) {
        log.warning('News-Article %s does not contain an image', node._displayName);
    const imageName = getFileName(imgSrc);

    //"Fetching image...")
    const resp = httpClient.request({
        url: imgSrc

    const cTypes = resp.contentType.split(';');

    //let imageNode;
    let imageAttachment
    if (resp.status === 200) {
        imageAttachment = contentLib.addAttachment({
            key: node._path,
            name: imageName ? imageName : "Image",
            mimeType: cTypes[0],
            //label: 'news-image',
            data: resp.bodyStream

function saveToRepo(item, root, site_path) {
    try {
        const name = 'market_news_' + item.guid.contents;
        const date = new Date(item.pubDate);
        const year = date.getFullYear().toString();
        const month = ("0" + (date.getMonth() + 1)).slice(-2);

        const newMarketNews = contentLib.create({
            name: name,
            displayName: item.title,
            contentType: `${}:marketNews`,
            requireValid: false,
            parentPath: `${site_path}/${root}/${year}/${month}`,
            data: item


        // publish direct
        if (newMarketNews) {
                    keys: [newMarketNews._id],
                    sourceBranch: 'draft',
                    targetBranch: 'master'


        return 1;

    } catch (e) {
        if (e.code === 'contentAlreadyExists') {
            return 0;
        } else {
            log.error('Unexpected error: (%s) %s ', e.code, e.message);
            return 0;


function getFileName(url) {
    return url.split('?')[0].split('/').pop();

/*** check if a folder exits ***/
function checkFolderExists(path) {
    return contentLib.exists({key: path})

 * execute a function in admin context
 * @param callback callback function to execute in the context
 * @returns {*} whatever the function returns
const runInContext = function (callback, repository) {
    let result;
    try {
        result ={
            principals: ["role:system.admin"],
            user: {login: 'su'},
            repository: repository,

        }, callback);
    } catch (e) {'Error: ' + e.message);

    return result;

I guess this is the “original” code, before transpilation by Tsup? I meant how does it look after transpilation (in the /build/ folder).

Unfortunately this is the code, extracted from the jar-file in the build-folder :man_shrugging:

This is from a webpack-project - but I started migrating to tsup-project and there it is working :slight_smile:

Ok, I think I know what the issue is. The “Missing task script” error you get means that there’s a code which tries to submit a task which doesn’t have corresponding definition under /resources/tasks.

In the case of Tsup starter, you probably deleted the task folder under /resources/tasks but forgot to remove the code which submits the task in main.js

Unfortunately that is not the case. I have the script in the right folder and it is the same as before.

I started with a simple Vanilla-Starter and converted the project to a webpack-project to use ECMAScript/TypeScript).

In Vaniila my task worked ind webpack not.

Then I decided to migrate to tsup-starter-project. There it works again. As I have refactored the code massively, I can not say what the reason was.

I would say, we shoul not investigate more time in the old code. In any case, thank you very much for your efforts.

1 Like

Missing task script is also reported then js file cannot be loaded properly. For instance, if it requires (imports) missing library.